Chromium Code Reviews| Index: net/quic/crypto/channel_id_nss.cc |
| =================================================================== |
| --- net/quic/crypto/channel_id_nss.cc (revision 203993) |
| +++ net/quic/crypto/channel_id_nss.cc (working copy) |
| @@ -4,17 +4,82 @@ |
| #include "net/quic/crypto/channel_id.h" |
| +#include <keythi.h> |
| +#include <pk11pub.h> |
| +#include <sechash.h> |
| + |
| +#include "base/logging.h" |
| + |
| using base::StringPiece; |
| +using std::string; |
| namespace net { |
| -// TODO(rtenneti): Implement NSS support for ChannelIDVerifier::Verify and |
| -// real ChannelIDSigner (using the SpdyCredentialBuilder as a model). |
| // static |
| bool ChannelIDVerifier::Verify(StringPiece key, |
| StringPiece signed_data, |
| StringPiece signature) { |
| - return true; |
| + return VerifyRaw(key, signed_data, signature, true); |
| } |
| +// static |
| +bool ChannelIDVerifier::VerifyRaw(StringPiece key, |
| + StringPiece signed_data, |
| + StringPiece signature, |
| + bool is_channel_id_signature) { |
| + if (key.size() != 32 * 2 || |
| + signature.size() != 32 * 2) { |
| + return false; |
| + } |
| + |
| + SECKEYPublicKey public_key; |
| + memset(&public_key, 0, sizeof(public_key)); |
| + |
| + // The object identifier (OID) of the named curve P-256. |
| + static const unsigned char p256_oid[] = { |
| + 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07 |
| + }; |
| + public_key.keyType = ecKey; |
| + public_key.u.ec.DEREncodedParams.type = siBuffer; |
| + public_key.u.ec.DEREncodedParams.data = const_cast<unsigned char*>(p256_oid); |
| + public_key.u.ec.DEREncodedParams.len = sizeof(p256_oid); |
| + |
| + unsigned char key_buf[65]; |
| + key_buf[0] = 0x04; |
| + memcpy(&key_buf[1], key.data(), key.size()); |
| + public_key.u.ec.publicValue.type = siBuffer; |
| + public_key.u.ec.publicValue.data = key_buf; |
| + public_key.u.ec.publicValue.len = sizeof(key_buf); |
| + |
| + SECItem signature_item = { |
| + siBuffer, |
| + reinterpret_cast<unsigned char*>(const_cast<char*>(signature.data())), |
| + signature.size() |
| + }; |
| + |
| + unsigned char hash_buf[SHA256_LENGTH]; |
| + SECItem hash_item = { siBuffer, hash_buf, sizeof(hash_buf) }; |
| + |
| + HASHContext* sha256 = HASH_Create(HASH_AlgSHA256); |
| + if (!sha256) { |
| + return false; |
| + } |
| + HASH_Begin(sha256); |
| + if (is_channel_id_signature) { |
| + HASH_Update(sha256, reinterpret_cast<const unsigned char*>(kContextStr), |
| + strlen(kContextStr) + 1); |
| + HASH_Update(sha256, |
| + reinterpret_cast<const unsigned char*>(kClientToServerStr), |
| + strlen(kClientToServerStr) + 1); |
| + } |
| + HASH_Update(sha256, |
| + reinterpret_cast<const unsigned char*>(signed_data.data()), |
| + signed_data.size()); |
| + HASH_End(sha256, hash_buf, &hash_item.len, sizeof(hash_buf)); |
| + HASH_Destroy(sha256); |
| + |
| + SECStatus rv = PK11_Verify(&public_key, &signature_item, &hash_item, NULL); |
|
agl
2013/06/12 15:29:57
nit: seems that these two lines could be merged al
wtc
2013/06/12 18:11:01
Done.
|
| + return rv == SECSuccess; |
| +} |
| + |
| } // namespace net |