blob: fca982a5647aead11edb6e96c7c5dc72aa8842c4 [file] [log] [blame]
Yingdi Yub263f152015-07-12 16:50:13 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
Davide Pesavento87039532017-09-16 15:15:39 -04002/*
3 * Copyright (c) 2013-2017 Regents of the University of California.
Yingdi Yub263f152015-07-12 16:50:13 -07004 *
5 * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
6 *
7 * ndn-cxx library is free software: you can redistribute it and/or modify it under the
8 * terms of the GNU Lesser General Public License as published by the Free Software
9 * Foundation, either version 3 of the License, or (at your option) any later version.
10 *
11 * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
12 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
13 * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
14 *
15 * You should have received copies of the GNU General Public License and GNU Lesser
16 * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
17 * <http://www.gnu.org/licenses/>.
18 *
19 * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
20 */
21
22#include "verifier-filter.hpp"
Davide Pesavento8aad3722017-09-16 20:57:28 -040023#include "public-key.hpp"
Davide Pesavento87039532017-09-16 15:15:39 -040024#include "../detail/openssl-helper.hpp"
25
26#include <boost/lexical_cast.hpp>
Yingdi Yub263f152015-07-12 16:50:13 -070027
28namespace ndn {
29namespace security {
30namespace transform {
31
32class VerifierFilter::Impl
33{
34public:
Davide Pesavento3504cc42017-09-17 15:28:10 -040035 Impl(const uint8_t* sig, size_t siglen)
Davide Pesavento8a14b9b2017-09-17 01:26:06 -040036 : sig(sig)
37 , siglen(siglen)
Yingdi Yub263f152015-07-12 16:50:13 -070038 {
Yingdi Yub263f152015-07-12 16:50:13 -070039 }
40
41public:
Davide Pesavento3504cc42017-09-17 15:28:10 -040042 detail::EvpMdCtx ctx;
Davide Pesavento8a14b9b2017-09-17 01:26:06 -040043 const uint8_t* sig;
44 size_t siglen;
Yingdi Yub263f152015-07-12 16:50:13 -070045};
46
Davide Pesavento8aad3722017-09-16 20:57:28 -040047
Yingdi Yub263f152015-07-12 16:50:13 -070048VerifierFilter::VerifierFilter(DigestAlgorithm algo, const PublicKey& key,
49 const uint8_t* sig, size_t sigLen)
Davide Pesavento8a14b9b2017-09-17 01:26:06 -040050 : m_impl(make_unique<Impl>(sig, sigLen))
Yingdi Yub263f152015-07-12 16:50:13 -070051{
Davide Pesavento87039532017-09-16 15:15:39 -040052 const EVP_MD* md = detail::digestAlgorithmToEvpMd(algo);
53 if (md == nullptr)
54 BOOST_THROW_EXCEPTION(Error(getIndex(), "Unsupported digest algorithm " +
55 boost::lexical_cast<std::string>(algo)));
Yingdi Yub263f152015-07-12 16:50:13 -070056
Davide Pesavento8a14b9b2017-09-17 01:26:06 -040057 if (EVP_DigestVerifyInit(m_impl->ctx, nullptr, md, nullptr,
58 reinterpret_cast<EVP_PKEY*>(key.getEvpPkey())) != 1)
59 BOOST_THROW_EXCEPTION(Error(getIndex(), "Failed to initialize verification context with " +
60 boost::lexical_cast<std::string>(algo) + " digest and " +
61 boost::lexical_cast<std::string>(key.getKeyType()) + " key"));
Yingdi Yub263f152015-07-12 16:50:13 -070062}
63
Davide Pesavento8aad3722017-09-16 20:57:28 -040064VerifierFilter::~VerifierFilter() = default;
65
Yingdi Yub263f152015-07-12 16:50:13 -070066size_t
67VerifierFilter::convert(const uint8_t* buf, size_t size)
68{
Davide Pesavento8a14b9b2017-09-17 01:26:06 -040069 if (EVP_DigestVerifyUpdate(m_impl->ctx, buf, size) != 1)
70 BOOST_THROW_EXCEPTION(Error(getIndex(), "Failed to accept more input"));
Yingdi Yub263f152015-07-12 16:50:13 -070071
Davide Pesavento8a14b9b2017-09-17 01:26:06 -040072 return size;
Yingdi Yub263f152015-07-12 16:50:13 -070073}
74
75void
76VerifierFilter::finalize()
77{
Davide Pesavento8a14b9b2017-09-17 01:26:06 -040078 int res = EVP_DigestVerifyFinal(m_impl->ctx,
79#if OPENSSL_VERSION_NUMBER < 0x1000200fL
80 const_cast<uint8_t*>(m_impl->sig),
81#else
82 m_impl->sig,
83#endif
84 m_impl->siglen);
85
Yingdi Yub263f152015-07-12 16:50:13 -070086 auto buffer = make_unique<OBuffer>(1);
Davide Pesavento8a14b9b2017-09-17 01:26:06 -040087 (*buffer)[0] = (res == 1) ? 1 : 0;
Yingdi Yub263f152015-07-12 16:50:13 -070088 setOutputBuffer(std::move(buffer));
89
90 flushAllOutput();
91}
92
93unique_ptr<Transform>
94verifierFilter(DigestAlgorithm algo, const PublicKey& key,
95 const uint8_t* sig, size_t sigLen)
96{
97 return make_unique<VerifierFilter>(algo, key, sig, sigLen);
98}
99
100} // namespace transform
101} // namespace security
102} // namespace ndn