blob: 778f612923907a1cf2420369badbb610e6dc8a3f [file] [log] [blame]
Jeff Thompson3a2eb2f2013-12-11 11:00:27 -08001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
2/**
3 * Copyright (C) 2013 Regents of the University of California.
4 * @author: Yingdi Yu <yingdi@cs.ucla.edu>
5 * @author: Jeff Thompson <jefft0@remap.ucla.edu>
6 * See COPYING for copyright and distribution information.
7 */
8
9#include "../../c/util/crypto.h"
10#include <ndn-cpp/sha256-with-rsa-signature.hpp>
11#include <ndn-cpp/security/security-exception.hpp>
12#include <ndn-cpp/security/identity/identity-storage.hpp>
13#include <ndn-cpp/security/policy/self-verify-policy-manager.hpp>
14
15using namespace std;
16using namespace ndn::ptr_lib;
17
18namespace ndn {
19
20/**
21 * Verify the signature on the data packet using the given public key. If there is no data.getDefaultWireEncoding(),
22 * this calls data.wireEncode() to set it.
23 * TODO: Move this general verification code to a more central location.
24 * @param data The data packet with the signed portion and the signature to verify. The data packet must have a
25 * Sha256WithRsaSignature.
26 * @param publicKeyDer The DER-encoded public key used to verify the signature.
27 * @return true if the signature verifies, false if not.
28 * @throw SecurityException if data does not have a Sha256WithRsaSignature.
29 */
30static bool
31verifySha256WithRsaSignature(const Data& data, const Blob& publicKeyDer)
32{
33 const Sha256WithRsaSignature *signature = dynamic_cast<const Sha256WithRsaSignature*>(data.getSignature());
34 if (!signature)
35 throw SecurityException("signature is not Sha256WithRsaSignature.");
36
37 // Set the data packet's default wire encoding if it is not already there.
38 if (signature->getDigestAlgorithm().size() != 0)
39 // TODO: Allow a non-default digest algorithm.
40 throw UnrecognizedDigestAlgorithmException("Cannot verify a data packet with a non-default digest algorithm.");
41 if (!data.getDefaultWireEncoding())
42 data.wireEncode();
43
44 // Set signedPortionDigest to the digest of the signed portion of the wire encoding.
45 uint8_t signedPortionDigest[SHA256_DIGEST_LENGTH];
46 ndn_digestSha256(data.getDefaultWireEncoding().signedBuf(), data.getDefaultWireEncoding().signedSize(), signedPortionDigest);
47
48 // Verify the signedPortionDigest.
49 // Use a temporary pointer since d2i updates it.
50 const uint8_t *derPointer = publicKeyDer.buf();
51 RSA *rsaPublicKey = d2i_RSA_PUBKEY(NULL, &derPointer, publicKeyDer.size());
52 if (!rsaPublicKey)
53 throw UnrecognizedKeyFormatException("Error decoding public key in d2i_RSAPublicKey");
54 int success = RSA_verify
55 (NID_sha256, signedPortionDigest, sizeof(signedPortionDigest), (uint8_t *)signature->getSignature().buf(),
56 signature->getSignature().size(), rsaPublicKey);
57 // Free the public key before checking for success.
58 RSA_free(rsaPublicKey);
59
60 // RSA_verify returns 1 for a valid signature.
61 return (success == 1);
62}
63
64SelfVerifyPolicyManager::~SelfVerifyPolicyManager()
65{
66}
67
68bool
69SelfVerifyPolicyManager::skipVerifyAndTrust(const Data& data)
70{
71 return false;
72}
73
74bool
75SelfVerifyPolicyManager::requireVerify(const Data& data)
76{
77 return true;
78}
79
80shared_ptr<ValidationRequest>
81SelfVerifyPolicyManager::checkVerificationPolicy
82 (const shared_ptr<Data>& data, int stepCount, const OnVerified& onVerified, const OnVerifyFailed& onVerifyFailed)
83{
84 // Case to const Data* so that we use the const version of getSignature() and don't reset the default encoding.
85 const Sha256WithRsaSignature *signature = dynamic_cast<const Sha256WithRsaSignature*>(((const Data*)data.get())->getSignature());
86 if (!signature)
87 throw SecurityException("SelfVerifyPolicyManager: Signature is not Sha256WithRsaSignature.");
88
89 if (signature->getKeyLocator().getType() == ndn_KeyLocatorType_KEY) {
90 // Use the public key DER directly.
91 if (verifySha256WithRsaSignature(*data, signature->getKeyLocator().getKeyData()))
92 onVerified(data);
93 else
94 onVerifyFailed(data);
95 }
96 else if (signature->getKeyLocator().getType() == ndn_KeyLocatorType_KEYNAME && identityStorage_) {
97 // Assume the key name is a certificate name.
98 Blob publicKeyDer = identityStorage_->getKey
99 (IdentityCertificate::certificateNameToPublicKeyName(signature->getKeyLocator().getKeyName()));
100 if (!publicKeyDer)
101 // Can't find the public key with the name.
102 onVerifyFailed(data);
103
104 if (verifySha256WithRsaSignature(*data, publicKeyDer))
105 onVerified(data);
106 else
107 onVerifyFailed(data);
108 }
109 else
110 // Can't find a key to verify.
111 onVerifyFailed(data);
112
113 // No more steps, so return a null ValidationRequest.
114 return shared_ptr<ValidationRequest>();
115}
116
117bool
118SelfVerifyPolicyManager::checkSigningPolicy(const Name& dataName, const Name& certificateName)
119{
120 return true;
121}
122
123Name
124SelfVerifyPolicyManager::inferSigningIdentity(const Name& dataName)
125{
126 return Name();
127}
128
129}