OLD | NEW |
---|---|
(Empty) | |
1 // Copyright 2015 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/internal/signature_algorithm.h" | |
6 | |
7 #include <stdint.h> | |
8 | |
9 #include "net/der/input.h" | |
10 #include "net/der/parser.h" | |
11 | |
12 namespace net { | |
13 | |
14 namespace { | |
15 | |
16 // From RFC 3279 section 2.2.1: | |
17 // sha-1WithRSAEncryption OBJECT IDENTIFIER ::= { | |
18 // iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) | |
19 // pkcs-1(1) 5 } | |
20 // In dotted notation: 1.2.840.113549.1.1.5 | |
21 const uint8_t kOidSha1WithRsaEncryption[] = | |
22 {0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05}; | |
23 | |
24 // From RFC 4055 section 6: | |
25 // pkcs-1 OBJECT IDENTIFIER ::= { iso(1) member-body(2) | |
26 // us(840) rsadsi(113549) pkcs(1) 1 } | |
27 | |
28 // From RFC 4055 section 5: | |
29 // sha256WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 11 } | |
30 // In dotted notation: 1.2.840.113549.1.1.11 | |
31 const uint8_t kOidSha256WithRsaEncryption[] = | |
32 {0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b}; | |
33 | |
34 // From RFC 4055 section 5: | |
35 // sha384WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 12 } | |
36 // In dotted notation: 1.2.840.113549.1.1.12 | |
37 const uint8_t kOidSha384WithRsaEncryption[] = | |
38 {0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0c}; | |
39 | |
40 // From RFC 4055 section 5: | |
41 // sha512WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 13 } | |
42 // In dotted notation: 1.2.840.113549.1.1.13 | |
43 const uint8_t kOidSha512WithRsaEncryption[] = | |
44 {0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0d}; | |
45 | |
46 // From RFC 3279 section 2.2.3: | |
47 // ansi-X9-62 OBJECT IDENTIFIER ::= { | |
48 // iso(1) member-body(2) us(840) 10045 } | |
49 // | |
50 // id-ecSigType OBJECT IDENTIFIER ::= { | |
51 // ansi-X9-62 signatures(4) } | |
52 // | |
53 // ecdsa-with-SHA1 OBJECT IDENTIFIER ::= { | |
54 // id-ecSigType 1 } | |
55 // In dotted notation: 1.2.840.10045.4.1 | |
56 const uint8_t kOidEcdsaWithSha1[] = {0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x01}; | |
57 | |
58 // From RFC 5758 section 3.2: | |
59 // ecdsa-with-SHA256 OBJECT IDENTIFIER ::= { iso(1) member-body(2) | |
60 // us(840) ansi-X9-62(10045) signatures(4) ecdsa-with-SHA2(3) 2 } | |
61 // In dotted notation: 1.2.840.10045.4.3.2 | |
62 const uint8_t kOidEcdsaWithSha256[] = | |
63 {0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02}; | |
64 | |
65 // From RFC 5758 section 3.2: | |
66 // ecdsa-with-SHA384 OBJECT IDENTIFIER ::= { iso(1) member-body(2) | |
67 // us(840) ansi-X9-62(10045) signatures(4) ecdsa-with-SHA2(3) 3 } | |
68 // In dotted notation: 1.2.840.10045.4.3.3 | |
69 const uint8_t kOidEcdsaWithSha384[] = | |
70 {0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x03}; | |
71 | |
72 // From RFC 5758 section 3.2: | |
73 // ecdsa-with-SHA512 OBJECT IDENTIFIER ::= { iso(1) member-body(2) | |
74 // us(840) ansi-X9-62(10045) signatures(4) ecdsa-with-SHA2(3) 4 } | |
75 // In dotted notation: 1.2.840.10045.4.3.4 | |
76 const uint8_t kOidEcdsaWithSha512[] = | |
77 {0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x04}; | |
78 | |
79 // Assigns |out| with the values |algorithm| and |digest|. The passed in | |
80 // |algorithm_identifier_parser| is expected to be positioned after the | |
81 // algorithm OID. The parameters field will be consumed, and it must be either | |
82 // NULL or missing. | |
83 // | |
84 // Returns true on success. | |
85 WARN_UNUSED_RESULT bool AssignFromDerEmptyParams( | |
Ryan Sleevi
2015/06/29 14:45:24
end of line, not beginning.
eroman
2015/06/29 15:19:00
OK, I changed the other instance, but had to leave
Ryan Sleevi
2015/06/29 16:06:57
Yeah, this is part of why Peter and several others
| |
86 SignatureAlgorithmId algorithm, | |
87 DigestAlgorithmId digest, | |
88 der::Parser* algorithm_identifier_parser, | |
89 SignatureAlgorithm* out) { | |
90 // The specifications for RSA PKCS #1 v1.5 and ECDSA signature algorithm are | |
91 // inconsistent on whether the parameters field must be NULL, omitted, or can | |
92 // be either. | |
93 // | |
94 // This implementation is more permissive, and will accept both NULL and | |
95 // omitted parameters. | |
96 // | |
97 // For reference... | |
98 // | |
99 // RFC 5758 section-3.2: | |
100 // When the ecdsa-with-SHA224, ecdsa-with-SHA256, ecdsa-with-SHA384, or | |
101 // ecdsa-with-SHA512 algorithm identifier appears in the algorithm field | |
102 // as an AlgorithmIdentifier, the encoding MUST omit the parameters | |
103 // field. That is, the AlgorithmIdentifier SHALL be a SEQUENCE of one | |
104 // component, the OID ecdsa-with-SHA224, ecdsa-with-SHA256, ecdsa-with- | |
105 // SHA384, or ecdsa-with-SHA512. | |
106 // | |
107 // RFC 3279 section 2.2.1 (in reference to sha-1WithRSAEncryption): | |
108 // When any of these three OIDs appears within the ASN.1 type | |
109 // AlgorithmIdentifier, the parameters component of that type SHALL be | |
110 // the ASN.1 type NULL. | |
111 // | |
112 // RFC 3279 section 2.2.3: | |
113 // When the ecdsa-with-SHA1 algorithm identifier appears as the | |
114 // algorithm field in an AlgorithmIdentifier, the encoding MUST omit the | |
115 // parameters field. That is, the AlgorithmIdentifier SHALL be a | |
116 // SEQUENCE of one component: the OBJECT IDENTIFIER ecdsa-with-SHA1. | |
117 // | |
118 // RFC 4055 section 5 (in reference to sha256WithRSAEncryption et al): | |
119 // When any of these four object identifiers appears within an | |
120 // AlgorithmIdentifier, the parameters MUST be NULL. Implementations | |
121 // MUST accept the parameters being absent as well as present. | |
122 | |
123 if (algorithm_identifier_parser->HasMore()) { | |
124 der::Input null_value; | |
125 if (!algorithm_identifier_parser->ReadTag(der::kNull, &null_value)) | |
126 return false; | |
127 | |
128 if (null_value.Length() != 0) | |
129 return false; // Not a NULL value | |
130 | |
131 // After consuming the NULL params there shouldn't be anything left. | |
132 if (algorithm_identifier_parser->HasMore()) | |
133 return false; | |
134 } | |
135 | |
136 out->algorithm = algorithm; | |
137 out->digest = digest; | |
138 | |
139 return true; | |
140 } | |
141 | |
142 } // namespace | |
143 | |
144 bool SignatureAlgorithm::AssignFromDer(const der::Input& in) { | |
145 // RFC 5280 section 4.1.1.2 defines signatureAlgorithm as: | |
146 // | |
147 // AlgorithmIdentifier ::= SEQUENCE { | |
148 // algorithm OBJECT IDENTIFIER, | |
149 // parameters ANY DEFINED BY algorithm OPTIONAL } | |
150 | |
151 der::Parser parser(in); | |
152 | |
153 der::Parser algorithm_identifier_parser; | |
154 if (!parser.ReadSequence(&algorithm_identifier_parser)) | |
155 return false; | |
156 | |
157 der::Input oid; | |
158 if (!algorithm_identifier_parser.ReadTag(der::kOid, &oid)) | |
159 return false; | |
160 | |
161 // TODO(eroman): Each OID is tested for equality in order, which is not | |
162 // particularly efficient. | |
163 | |
164 if (oid.Equals(kOidSha1WithRsaEncryption)) { | |
165 return AssignFromDerEmptyParams(SignatureAlgorithmId::RsaPkcs1_5, | |
166 DigestAlgorithmId::Sha1, | |
167 &algorithm_identifier_parser, this); | |
168 } | |
169 | |
170 if (oid.Equals(kOidSha256WithRsaEncryption)) { | |
171 return AssignFromDerEmptyParams(SignatureAlgorithmId::RsaPkcs1_5, | |
172 DigestAlgorithmId::Sha256, | |
173 &algorithm_identifier_parser, this); | |
174 } | |
175 | |
176 if (oid.Equals(kOidSha384WithRsaEncryption)) { | |
177 return AssignFromDerEmptyParams(SignatureAlgorithmId::RsaPkcs1_5, | |
178 DigestAlgorithmId::Sha384, | |
179 &algorithm_identifier_parser, this); | |
180 } | |
181 | |
182 if (oid.Equals(kOidSha512WithRsaEncryption)) { | |
183 return AssignFromDerEmptyParams(SignatureAlgorithmId::RsaPkcs1_5, | |
184 DigestAlgorithmId::Sha512, | |
185 &algorithm_identifier_parser, this); | |
186 } | |
187 | |
188 if (oid.Equals(kOidEcdsaWithSha1)) { | |
189 return AssignFromDerEmptyParams(SignatureAlgorithmId::Ecdsa, | |
190 DigestAlgorithmId::Sha1, | |
191 &algorithm_identifier_parser, this); | |
192 } | |
193 | |
194 if (oid.Equals(kOidEcdsaWithSha256)) { | |
195 return AssignFromDerEmptyParams(SignatureAlgorithmId::Ecdsa, | |
196 DigestAlgorithmId::Sha256, | |
197 &algorithm_identifier_parser, this); | |
198 } | |
199 | |
200 if (oid.Equals(kOidEcdsaWithSha384)) { | |
201 return AssignFromDerEmptyParams(SignatureAlgorithmId::Ecdsa, | |
202 DigestAlgorithmId::Sha384, | |
203 &algorithm_identifier_parser, this); | |
204 } | |
205 | |
206 if (oid.Equals(kOidEcdsaWithSha512)) { | |
207 return AssignFromDerEmptyParams(SignatureAlgorithmId::Ecdsa, | |
208 DigestAlgorithmId::Sha512, | |
209 &algorithm_identifier_parser, this); | |
210 } | |
211 | |
212 return false; // Unsupported OID. | |
213 } | |
214 | |
215 bool SignatureAlgorithm::Equals(const SignatureAlgorithm& other) const { | |
216 return algorithm == other.algorithm && digest == other.digest; | |
217 } | |
218 | |
219 } // namespace net | |
OLD | NEW |