1// Copyright 2013 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "net/quic/crypto/channel_id.h" 6 7#include <keythi.h> 8#include <pk11pub.h> 9#include <sechash.h> 10 11using base::StringPiece; 12 13namespace net { 14 15// static 16bool ChannelIDVerifier::Verify(StringPiece key, 17 StringPiece signed_data, 18 StringPiece signature) { 19 return VerifyRaw(key, signed_data, signature, true); 20} 21 22// static 23bool ChannelIDVerifier::VerifyRaw(StringPiece key, 24 StringPiece signed_data, 25 StringPiece signature, 26 bool is_channel_id_signature) { 27 if (key.size() != 32 * 2 || 28 signature.size() != 32 * 2) { 29 return false; 30 } 31 32 SECKEYPublicKey public_key; 33 memset(&public_key, 0, sizeof(public_key)); 34 35 // DER encoding of the object identifier (OID) of the named curve P-256 36 // (1.2.840.10045.3.1.7). See RFC 6637 Section 11. 37 static const unsigned char p256_oid[] = { 38 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07 39 }; 40 public_key.keyType = ecKey; 41 public_key.u.ec.DEREncodedParams.type = siBuffer; 42 public_key.u.ec.DEREncodedParams.data = const_cast<unsigned char*>(p256_oid); 43 public_key.u.ec.DEREncodedParams.len = sizeof(p256_oid); 44 45 unsigned char key_buf[65]; 46 key_buf[0] = 0x04; 47 memcpy(&key_buf[1], key.data(), key.size()); 48 public_key.u.ec.publicValue.type = siBuffer; 49 public_key.u.ec.publicValue.data = key_buf; 50 public_key.u.ec.publicValue.len = sizeof(key_buf); 51 52 SECItem signature_item = { 53 siBuffer, 54 reinterpret_cast<unsigned char*>(const_cast<char*>(signature.data())), 55 static_cast<unsigned int>(signature.size()) 56 }; 57 58 unsigned char hash_buf[SHA256_LENGTH]; 59 SECItem hash_item = { siBuffer, hash_buf, sizeof(hash_buf) }; 60 61 HASHContext* sha256 = HASH_Create(HASH_AlgSHA256); 62 if (!sha256) { 63 return false; 64 } 65 HASH_Begin(sha256); 66 if (is_channel_id_signature) { 67 HASH_Update(sha256, reinterpret_cast<const unsigned char*>(kContextStr), 68 strlen(kContextStr) + 1); 69 HASH_Update(sha256, 70 reinterpret_cast<const unsigned char*>(kClientToServerStr), 71 strlen(kClientToServerStr) + 1); 72 } 73 HASH_Update(sha256, 74 reinterpret_cast<const unsigned char*>(signed_data.data()), 75 signed_data.size()); 76 HASH_End(sha256, hash_buf, &hash_item.len, sizeof(hash_buf)); 77 HASH_Destroy(sha256); 78 79 return PK11_Verify(&public_key, &signature_item, &hash_item, NULL) == 80 SECSuccess; 81} 82 83} // namespace net 84