blob: ec974175c1cad417fe5dd3d7bffc01d6044a0992 [file] [log] [blame]
[email protected]41dd1852013-08-07 12:34:541// 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/cert/jwk_serializer.h"
6
peter527b9df2015-12-07 15:37:347#include "base/base64url.h"
[email protected]41dd1852013-08-07 12:34:548#include "base/values.h"
9#include "testing/gtest/include/gtest/gtest.h"
10
11namespace net {
12
peter527b9df2015-12-07 15:37:3413namespace {
14
[email protected]41dd1852013-08-07 12:34:5415// This is the ASN.1 prefix for a P-256 public key. Specifically it's:
16// SEQUENCE
17// SEQUENCE
18// OID id-ecPublicKey
19// OID prime256v1
20// BIT STRING, length 66, 0 trailing bits: 0x04
21//
22// The 0x04 in the BIT STRING is the prefix for an uncompressed, X9.62
23// public key. Following that are the two field elements as 32-byte,
24// big-endian numbers, as required by the Channel ID.
25static const unsigned char kP256SpkiPrefix[] = {
26 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86,
27 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a,
28 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03,
29 0x42, 0x00, 0x04
30};
[email protected]10a748252013-08-10 14:19:0931static const unsigned int kEcCoordinateSize = 32U;
[email protected]41dd1852013-08-07 12:34:5432
33// This is a valid P-256 public key.
34static const unsigned char kSpkiEc[] = {
35 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86,
36 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a,
37 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03,
38 0x42, 0x00, 0x04,
39 0x29, 0x5d, 0x6e, 0xfe, 0x33, 0x77, 0x26, 0xea,
40 0x5b, 0xa4, 0xe6, 0x1b, 0x34, 0x6e, 0x7b, 0xa0,
41 0xa3, 0x8f, 0x33, 0x49, 0xa0, 0x9c, 0xae, 0x98,
42 0xbd, 0x46, 0x0d, 0xf6, 0xd4, 0x5a, 0xdc, 0x8a,
43 0x1f, 0x8a, 0xb2, 0x20, 0x51, 0xb7, 0xd2, 0x87,
44 0x0d, 0x53, 0x7e, 0x5d, 0x94, 0xa3, 0xe0, 0x34,
45 0x16, 0xa1, 0xcc, 0x10, 0x48, 0xcd, 0x70, 0x9c,
46 0x05, 0xd3, 0xd2, 0xca, 0xdf, 0x44, 0x2f, 0xf4
47};
48
[email protected]11f98092014-07-30 09:18:2249// This is a P-256 public key with a leading 0.
50static const unsigned char kSpkiEcWithLeadingZero[] = {
[email protected]41dd1852013-08-07 12:34:5451 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86,
52 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a,
53 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03,
54 0x42, 0x00, 0x04,
[email protected]11f98092014-07-30 09:18:2255 0x00, 0x8e, 0xd5, 0x49, 0x51, 0xad, 0x7d, 0xd3,
56 0x3a, 0x59, 0x86, 0xd1, 0x2c, 0xba, 0x05, 0xd3,
57 0xa6, 0x3c, 0x5d, 0x6d, 0x28, 0xde, 0x8f, 0xdd,
58 0xa5, 0x3d, 0x30, 0x18, 0x05, 0x86, 0x76, 0x9c,
59 0x7c, 0xa7, 0xba, 0x58, 0xea, 0x1a, 0x84, 0x19,
60 0x29, 0x0a, 0x15, 0x30, 0x7d, 0x6b, 0x00, 0x41,
61 0x64, 0x56, 0x84, 0x19, 0x54, 0x3e, 0x26, 0x13,
62 0xc9, 0x1e, 0x31, 0x89, 0xe2, 0x62, 0xcb, 0x3f
[email protected]41dd1852013-08-07 12:34:5463};
64
peter527b9df2015-12-07 15:37:3465// Section 2 of RFC 7515 defines that an URL-safe base64 encoding must be used
66// with all trailing '=' characters omitted. Returns whether the |input|
67// contains any of the forbidden base64 characters (+, -, =).
68bool ContainsNonUrlSafeBase64Characters(base::StringPiece input) {
69 return input.find_first_of("+-=") != std::string::npos;
70}
71
72} // namespace
73
[email protected]11f98092014-07-30 09:18:2274TEST(JwkSerializerTest, ConvertSpkiFromDerToJwkEc) {
[email protected]41dd1852013-08-07 12:34:5475 base::StringPiece spki;
76 base::DictionaryValue public_key_jwk;
77
78 EXPECT_FALSE(JwkSerializer::ConvertSpkiFromDerToJwk(spki, &public_key_jwk));
79 EXPECT_TRUE(public_key_jwk.empty());
80
81 // Test the result of a "normal" point on this curve.
82 spki.set(reinterpret_cast<const char*>(kSpkiEc), sizeof(kSpkiEc));
83 EXPECT_TRUE(JwkSerializer::ConvertSpkiFromDerToJwk(spki, &public_key_jwk));
84
85 std::string string_value;
[email protected]797985c2013-11-09 18:07:0886 EXPECT_TRUE(public_key_jwk.GetString("kty", &string_value));
[email protected]41dd1852013-08-07 12:34:5487 EXPECT_STREQ("EC", string_value.c_str());
88 EXPECT_TRUE(public_key_jwk.GetString("crv", &string_value));
89 EXPECT_STREQ("P-256", string_value.c_str());
90
91 EXPECT_TRUE(public_key_jwk.GetString("x", &string_value));
peter527b9df2015-12-07 15:37:3492 EXPECT_FALSE(ContainsNonUrlSafeBase64Characters(string_value));
[email protected]41dd1852013-08-07 12:34:5493 std::string decoded_coordinate;
peter527b9df2015-12-07 15:37:3494 EXPECT_TRUE(base::Base64UrlDecode(
95 string_value, base::Base64UrlDecodePolicy::DISALLOW_PADDING,
96 &decoded_coordinate));
[email protected]10a748252013-08-10 14:19:0997 EXPECT_EQ(kEcCoordinateSize, decoded_coordinate.size());
[email protected]41dd1852013-08-07 12:34:5498 EXPECT_EQ(0,
99 memcmp(decoded_coordinate.data(),
100 kSpkiEc + sizeof(kP256SpkiPrefix),
[email protected]10a748252013-08-10 14:19:09101 kEcCoordinateSize));
[email protected]41dd1852013-08-07 12:34:54102
103 EXPECT_TRUE(public_key_jwk.GetString("y", &string_value));
peter527b9df2015-12-07 15:37:34104 EXPECT_FALSE(ContainsNonUrlSafeBase64Characters(string_value));
105 EXPECT_TRUE(base::Base64UrlDecode(
106 string_value, base::Base64UrlDecodePolicy::DISALLOW_PADDING,
107 &decoded_coordinate));
[email protected]10a748252013-08-10 14:19:09108 EXPECT_EQ(kEcCoordinateSize, decoded_coordinate.size());
[email protected]41dd1852013-08-07 12:34:54109 EXPECT_EQ(0,
110 memcmp(decoded_coordinate.data(),
[email protected]10a748252013-08-10 14:19:09111 kSpkiEc + sizeof(kP256SpkiPrefix) + kEcCoordinateSize,
112 kEcCoordinateSize));
[email protected]41dd1852013-08-07 12:34:54113
114 // Test the result of a corner case: leading 0s in the x, y coordinates are
115 // not trimmed, but the point is fixed-length encoded.
[email protected]11f98092014-07-30 09:18:22116 spki.set(reinterpret_cast<const char*>(kSpkiEcWithLeadingZero),
117 sizeof(kSpkiEcWithLeadingZero));
[email protected]41dd1852013-08-07 12:34:54118 EXPECT_TRUE(JwkSerializer::ConvertSpkiFromDerToJwk(spki, &public_key_jwk));
119
[email protected]797985c2013-11-09 18:07:08120 EXPECT_TRUE(public_key_jwk.GetString("kty", &string_value));
[email protected]41dd1852013-08-07 12:34:54121 EXPECT_STREQ("EC", string_value.c_str());
122 EXPECT_TRUE(public_key_jwk.GetString("crv", &string_value));
123 EXPECT_STREQ("P-256", string_value.c_str());
124
125 EXPECT_TRUE(public_key_jwk.GetString("x", &string_value));
peter527b9df2015-12-07 15:37:34126 EXPECT_FALSE(ContainsNonUrlSafeBase64Characters(string_value));
127 EXPECT_TRUE(base::Base64UrlDecode(
128 string_value, base::Base64UrlDecodePolicy::DISALLOW_PADDING,
129 &decoded_coordinate));
[email protected]10a748252013-08-10 14:19:09130 EXPECT_EQ(kEcCoordinateSize, decoded_coordinate.size());
[email protected]41dd1852013-08-07 12:34:54131 EXPECT_EQ(0,
132 memcmp(decoded_coordinate.data(),
[email protected]11f98092014-07-30 09:18:22133 kSpkiEcWithLeadingZero + sizeof(kP256SpkiPrefix),
[email protected]10a748252013-08-10 14:19:09134 kEcCoordinateSize));
[email protected]41dd1852013-08-07 12:34:54135
136 EXPECT_TRUE(public_key_jwk.GetString("y", &string_value));
peter527b9df2015-12-07 15:37:34137 EXPECT_FALSE(ContainsNonUrlSafeBase64Characters(string_value));
138 EXPECT_TRUE(base::Base64UrlDecode(
139 string_value, base::Base64UrlDecodePolicy::DISALLOW_PADDING,
140 &decoded_coordinate));
[email protected]10a748252013-08-10 14:19:09141 EXPECT_EQ(kEcCoordinateSize, decoded_coordinate.size());
[email protected]11f98092014-07-30 09:18:22142 EXPECT_EQ(0, memcmp(
143 decoded_coordinate.data(),
144 kSpkiEcWithLeadingZero + sizeof(kP256SpkiPrefix) + kEcCoordinateSize,
145 kEcCoordinateSize));
[email protected]41dd1852013-08-07 12:34:54146}
147
[email protected]41dd1852013-08-07 12:34:54148} // namespace net