Home | History | Annotate | Download | only in crypto
      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
     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
     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