• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
11 using base::StringPiece;
12 
13 namespace net {
14 
15 // static
Verify(StringPiece key,StringPiece signed_data,StringPiece signature)16 bool ChannelIDVerifier::Verify(StringPiece key,
17                                StringPiece signed_data,
18                                StringPiece signature) {
19   return VerifyRaw(key, signed_data, signature, true);
20 }
21 
22 // static
VerifyRaw(StringPiece key,StringPiece signed_data,StringPiece signature,bool is_channel_id_signature)23 bool 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