Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(435)

Side by Side Diff: net/base/x509_util_nss.cc

Issue 8537025: Allow signing EC certs and creating EC origin-bound certs. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 9 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "net/base/x509_util.h" 5 #include "net/base/x509_util.h"
6 #include "net/base/x509_util_nss.h" 6 #include "net/base/x509_util_nss.h"
7 7
8 #include <cert.h> 8 #include <cert.h>
9 #include <cryptohi.h> 9 #include <cryptohi.h>
10 #include <pk11pub.h> 10 #include <pk11pub.h>
11 #include <prerror.h> 11 #include <prerror.h>
12 #include <secmod.h> 12 #include <secmod.h>
13 #include <secport.h> 13 #include <secport.h>
14 14
15 #include "base/debug/leak_annotations.h" 15 #include "base/debug/leak_annotations.h"
16 #include "base/logging.h" 16 #include "base/logging.h"
17 #include "base/memory/scoped_ptr.h" 17 #include "base/memory/scoped_ptr.h"
18 #include "base/memory/singleton.h" 18 #include "base/memory/singleton.h"
19 #include "crypto/ec_private_key.h"
19 #include "crypto/nss_util.h" 20 #include "crypto/nss_util.h"
20 #include "crypto/nss_util_internal.h" 21 #include "crypto/nss_util_internal.h"
21 #include "crypto/rsa_private_key.h" 22 #include "crypto/rsa_private_key.h"
22 #include "crypto/scoped_nss_types.h" 23 #include "crypto/scoped_nss_types.h"
24 #include "crypto/third_party/nss/chromium-nss.h"
23 25
24 namespace { 26 namespace {
25 27
26 class ObCertOIDWrapper { 28 class ObCertOIDWrapper {
27 public: 29 public:
28 static ObCertOIDWrapper* GetInstance() { 30 static ObCertOIDWrapper* GetInstance() {
29 // Instantiated as a leaky singleton to allow the singleton to be 31 // Instantiated as a leaky singleton to allow the singleton to be
30 // constructed on a worker thead that is not joined when a process 32 // constructed on a worker thead that is not joined when a process
31 // shuts down. 33 // shuts down.
32 return Singleton<ObCertOIDWrapper, 34 return Singleton<ObCertOIDWrapper,
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after
150 arena, &der, cert, SEC_ASN1_GET(CERT_CertificateTemplate)); 152 arena, &der, cert, SEC_ASN1_GET(CERT_CertificateTemplate));
151 if (!encode_result) 153 if (!encode_result)
152 return false; 154 return false;
153 155
154 // Allocate space to contain the signed cert. 156 // Allocate space to contain the signed cert.
155 SECItem* result = SECITEM_AllocItem(arena, NULL, 0); 157 SECItem* result = SECITEM_AllocItem(arena, NULL, 0);
156 if (!result) 158 if (!result)
157 return false; 159 return false;
158 160
159 // Sign the ASN1 encoded cert and save it to |result|. 161 // Sign the ASN1 encoded cert and save it to |result|.
160 rv = SEC_DerSignData(arena, result, der.data, der.len, key, algo_id); 162 rv = DerSignData(arena, result, &der, key, algo_id);
161 if (rv != SECSuccess) 163 if (rv != SECSuccess) {
164 DLOG(ERROR) << "DerSignData: " << PORT_GetError();
162 return false; 165 return false;
166 }
163 167
164 // Save the signed result to the cert. 168 // Save the signed result to the cert.
165 cert->derCert = *result; 169 cert->derCert = *result;
166 170
167 return true; 171 return true;
168 } 172 }
169 173
174 bool CreateOriginBoundCert(
wtc 2011/11/15 03:10:57 It may be better to name this function CreateOrigi
mattm 2011/11/15 05:42:31 Done.
175 SECKEYPublicKey* public_key,
176 SECKEYPrivateKey* private_key,
177 const std::string& origin,
178 uint32 serial_number,
179 base::TimeDelta valid_duration,
180 std::string* der_cert) {
181
182 CERTCertificate* cert = CreateCertificate(public_key,
183 "CN=anonymous.invalid",
184 serial_number,
185 valid_duration);
186
187 if (!cert)
188 return false;
189
190 // Create opaque handle used to add extensions later.
191 void* cert_handle;
192 if ((cert_handle = CERT_StartCertExtensions(cert)) == NULL) {
193 LOG(ERROR) << "Unable to get opaque handle for adding extensions";
194 CERT_DestroyCertificate(cert);
195 return false;
196 }
197
198 // Create SECItem for IA5String encoding.
199 SECItem origin_string_item = {
200 siAsciiString,
201 (unsigned char*)origin.data(),
202 origin.size()
203 };
204
205 // IA5Encode and arena allocate SECItem
206 SECItem* asn1_origin_string = SEC_ASN1EncodeItem(
207 cert->arena, NULL, &origin_string_item,
208 SEC_ASN1_GET(SEC_IA5StringTemplate));
209 if (asn1_origin_string == NULL) {
210 LOG(ERROR) << "Unable to get ASN1 encoding for origin in ob_cert extension";
211 CERT_DestroyCertificate(cert);
212 return false;
213 }
214
215 // Add the extension to the opaque handle
216 if (CERT_AddExtension(cert_handle,
217 ObCertOIDWrapper::GetInstance()->ob_cert_oid_tag(),
218 asn1_origin_string,
219 PR_TRUE, PR_TRUE) != SECSuccess){
220 LOG(ERROR) << "Unable to add origin bound cert extension to opaque handle";
221 CERT_DestroyCertificate(cert);
222 return false;
223 }
224
225 // Copy extension into x509 cert
226 if (CERT_FinishExtensions(cert_handle) != SECSuccess){
227 LOG(ERROR) << "Unable to copy extension to X509 cert";
228 CERT_DestroyCertificate(cert);
229 return false;
230 }
231
232 if (!SignCertificate(cert, private_key)) {
233 CERT_DestroyCertificate(cert);
234 return false;
235 }
236
237 DCHECK(cert->derCert.len);
238 // XXX copied from X509Certificate::GetDEREncoded
239 der_cert->clear();
240 der_cert->append(reinterpret_cast<char*>(cert->derCert.data),
241 cert->derCert.len);
242 CERT_DestroyCertificate(cert);
243 return true;
244 }
245
170 } // namespace 246 } // namespace
171 247
172 namespace net { 248 namespace net {
173 249
174 namespace x509_util { 250 namespace x509_util {
175 251
176 CERTCertificate* CreateSelfSignedCert( 252 CERTCertificate* CreateSelfSignedCert(
177 SECKEYPublicKey* public_key, 253 SECKEYPublicKey* public_key,
178 SECKEYPrivateKey* private_key, 254 SECKEYPrivateKey* private_key,
179 const std::string& subject, 255 const std::string& subject,
180 uint32 serial_number, 256 uint32 serial_number,
181 base::TimeDelta valid_duration) { 257 base::TimeDelta valid_duration) {
182 CERTCertificate* cert = CreateCertificate(public_key, 258 CERTCertificate* cert = CreateCertificate(public_key,
183 subject, 259 subject,
184 serial_number, 260 serial_number,
185 valid_duration); 261 valid_duration);
186 if (!cert) 262 if (!cert)
187 return NULL; 263 return NULL;
188 264
189 if (!SignCertificate(cert, private_key)) { 265 if (!SignCertificate(cert, private_key)) {
190 CERT_DestroyCertificate(cert); 266 CERT_DestroyCertificate(cert);
191 return NULL; 267 return NULL;
192 } 268 }
193 269
194 return cert; 270 return cert;
195 } 271 }
196 272
197 bool CreateOriginBoundCert( 273 bool CreateOriginBoundCertRSA(
198 crypto::RSAPrivateKey* key, 274 crypto::RSAPrivateKey* key,
199 const std::string& origin, 275 const std::string& origin,
200 uint32 serial_number, 276 uint32 serial_number,
201 base::TimeDelta valid_duration, 277 base::TimeDelta valid_duration,
202 std::string* der_cert) { 278 std::string* der_cert) {
203 DCHECK(key); 279 DCHECK(key);
204 280
205 SECKEYPublicKey* public_key; 281 SECKEYPublicKey* public_key;
206 SECKEYPrivateKey* private_key; 282 SECKEYPrivateKey* private_key;
207 #if defined(USE_NSS) 283 #if defined(USE_NSS)
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
242 318
243 public_key = SECKEY_ConvertToPublicKey(private_key); 319 public_key = SECKEY_ConvertToPublicKey(private_key);
244 if (!public_key) { 320 if (!public_key) {
245 NOTREACHED(); 321 NOTREACHED();
246 return NULL; 322 return NULL;
247 } 323 }
248 scoped_public_key.reset(public_key); 324 scoped_public_key.reset(public_key);
249 } 325 }
250 #endif 326 #endif
251 327
252 CERTCertificate* cert = CreateCertificate(public_key, 328 return CreateOriginBoundCert(public_key,
253 "CN=anonymous.invalid", 329 private_key,
254 serial_number, 330 origin,
255 valid_duration); 331 serial_number,
332 valid_duration,
333 der_cert);
334 }
256 335
257 if (!cert) 336 bool CreateOriginBoundCertEC(
258 return false; 337 crypto::ECPrivateKey* key,
259 338 const std::string& origin,
260 // Create opaque handle used to add extensions later. 339 uint32 serial_number,
261 void* cert_handle; 340 base::TimeDelta valid_duration,
262 if ((cert_handle = CERT_StartCertExtensions(cert)) == NULL) { 341 std::string* der_cert) {
263 LOG(ERROR) << "Unable to get opaque handle for adding extensions"; 342 DCHECK(key);
264 CERT_DestroyCertificate(cert); 343 return CreateOriginBoundCert(key->public_key(),
265 return false; 344 key->key(),
266 } 345 origin,
267 346 serial_number,
268 // Create SECItem for IA5String encoding. 347 valid_duration,
269 SECItem origin_string_item = { 348 der_cert);
270 siAsciiString,
271 (unsigned char*)origin.data(),
272 origin.size()
273 };
274
275 // IA5Encode and arena allocate SECItem
276 SECItem* asn1_origin_string = SEC_ASN1EncodeItem(
277 cert->arena, NULL, &origin_string_item,
278 SEC_ASN1_GET(SEC_IA5StringTemplate));
279 if (asn1_origin_string == NULL) {
280 LOG(ERROR) << "Unable to get ASN1 encoding for origin in ob_cert extension";
281 CERT_DestroyCertificate(cert);
282 return false;
283 }
284
285 // Add the extension to the opaque handle
286 if (CERT_AddExtension(cert_handle,
287 ObCertOIDWrapper::GetInstance()->ob_cert_oid_tag(),
288 asn1_origin_string,
289 PR_TRUE, PR_TRUE) != SECSuccess){
290 LOG(ERROR) << "Unable to add origin bound cert extension to opaque handle";
291 CERT_DestroyCertificate(cert);
292 return false;
293 }
294
295 // Copy extension into x509 cert
296 if (CERT_FinishExtensions(cert_handle) != SECSuccess){
297 LOG(ERROR) << "Unable to copy extension to X509 cert";
298 CERT_DestroyCertificate(cert);
299 return false;
300 }
301
302 if (!SignCertificate(cert, private_key)) {
303 CERT_DestroyCertificate(cert);
304 return false;
305 }
306
307 DCHECK(cert->derCert.len);
308 // XXX copied from X509Certificate::GetDEREncoded
309 der_cert->clear();
310 der_cert->append(reinterpret_cast<char*>(cert->derCert.data),
311 cert->derCert.len);
312 CERT_DestroyCertificate(cert);
313 return true;
314 } 349 }
315 350
316 } // namespace x509_util 351 } // namespace x509_util
317 352
318 } // namespace net 353 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698