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

Side by Side Diff: net/third_party/mozilla_security_manager/nsPKCS12Blob.cpp

Issue 8566056: This applies GUIDs to certificate and key nicknames when (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Review edits Created 9 years 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 /* ***** BEGIN LICENSE BLOCK ***** 1 /* ***** BEGIN LICENSE BLOCK *****
2 * Version: MPL 1.1/GPL 2.0/LGPL 2.1 2 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
3 * 3 *
4 * The contents of this file are subject to the Mozilla Public License Version 4 * The contents of this file are subject to the Mozilla Public License Version
5 * 1.1 (the "License"); you may not use this file except in compliance with 5 * 1.1 (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at 6 * the License. You may obtain a copy of the License at
7 * http://www.mozilla.org/MPL/ 7 * http://www.mozilla.org/MPL/
8 * 8 *
9 * Software distributed under the License is distributed on an "AS IS" basis, 9 * Software distributed under the License is distributed on an "AS IS" basis,
10 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 10 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
50 #include "net/base/x509_certificate.h" 50 #include "net/base/x509_certificate.h"
51 51
52 namespace mozilla_security_manager { 52 namespace mozilla_security_manager {
53 53
54 namespace { 54 namespace {
55 55
56 // unicodeToItem 56 // unicodeToItem
57 // 57 //
58 // For the NSS PKCS#12 library, must convert PRUnichars (shorts) to 58 // For the NSS PKCS#12 library, must convert PRUnichars (shorts) to
59 // a buffer of octets. Must handle byte order correctly. 59 // a buffer of octets. Must handle byte order correctly.
60 // TODO: Is there a mozilla way to do this? In the string lib? 60 // TODO: Is there a Mozilla way to do this? In the string lib?
61 void unicodeToItem(const PRUnichar *uni, SECItem *item) 61 void unicodeToItem(const PRUnichar *uni, SECItem *item)
62 { 62 {
63 int len = 0; 63 int len = 0;
64 while (uni[len++] != 0); 64 while (uni[len++] != 0);
65 SECITEM_AllocItem(NULL, item, sizeof(PRUnichar) * len); 65 SECITEM_AllocItem(NULL, item, sizeof(PRUnichar) * len);
66 #ifdef IS_LITTLE_ENDIAN 66 #ifdef IS_LITTLE_ENDIAN
67 int i = 0; 67 int i = 0;
68 for (i=0; i<len; i++) { 68 for (i=0; i<len; i++) {
69 item->data[2*i ] = (unsigned char )(uni[i] << 8); 69 item->data[2*i ] = (unsigned char )(uni[i] << 8);
70 item->data[2*i+1] = (unsigned char )(uni[i]); 70 item->data[2*i+1] = (unsigned char )(uni[i]);
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
131 PRBool 131 PRBool
132 pip_ucs2_ascii_conversion_fn(PRBool toUnicode, 132 pip_ucs2_ascii_conversion_fn(PRBool toUnicode,
133 unsigned char *inBuf, 133 unsigned char *inBuf,
134 unsigned int inBufLen, 134 unsigned int inBufLen,
135 unsigned char *outBuf, 135 unsigned char *outBuf,
136 unsigned int maxOutBufLen, 136 unsigned int maxOutBufLen,
137 unsigned int *outBufLen, 137 unsigned int *outBufLen,
138 PRBool swapBytes) 138 PRBool swapBytes)
139 { 139 {
140 CHECK_GE(maxOutBufLen, inBufLen); 140 CHECK_GE(maxOutBufLen, inBufLen);
141 // do a no-op, since I've already got unicode. Hah! 141 // do a no-op, since I've already got Unicode. Hah!
wtc 2011/11/29 23:13:57 In general it's not necessary to fix minor comment
142 *outBufLen = inBufLen; 142 *outBufLen = inBufLen;
143 memcpy(outBuf, inBuf, inBufLen); 143 memcpy(outBuf, inBuf, inBufLen);
144 return PR_TRUE; 144 return PR_TRUE;
145 } 145 }
146 146
147 // Based on nsPKCS12Blob::ImportFromFileHelper. 147 // Based on nsPKCS12Blob::ImportFromFileHelper.
148 int 148 int
149 nsPKCS12Blob_ImportHelper(const char* pkcs12_data, 149 nsPKCS12Blob_ImportHelper(const char* pkcs12_data,
150 size_t pkcs12_len, 150 size_t pkcs12_len,
151 const string16& password, 151 const string16& password,
152 bool is_extractable, 152 bool is_extractable,
153 bool try_zero_length_secitem, 153 bool try_zero_length_secitem,
154 PK11SlotInfo *slot) 154 PK11SlotInfo *slot,
155 net::CertificateList* imported_certs)
155 { 156 {
156 DCHECK(pkcs12_data); 157 DCHECK(pkcs12_data);
157 DCHECK(slot); 158 DCHECK(slot);
158 int import_result = net::ERR_PKCS12_IMPORT_FAILED; 159 int import_result = net::ERR_PKCS12_IMPORT_FAILED;
159 SECStatus srv = SECSuccess; 160 SECStatus srv = SECSuccess;
160 SEC_PKCS12DecoderContext *dcx = NULL; 161 SEC_PKCS12DecoderContext *dcx = NULL;
161 SECItem unicodePw; 162 SECItem unicodePw;
163 SECItem attribute_value;
164 CK_BBOOL attribute_data = CK_FALSE;
165 const SEC_PKCS12DecoderItem* decoder_item = NULL;
166
162 unicodePw.type = siBuffer; 167 unicodePw.type = siBuffer;
163 unicodePw.len = 0; 168 unicodePw.len = 0;
164 unicodePw.data = NULL; 169 unicodePw.data = NULL;
165 if (!try_zero_length_secitem) { 170 if (!try_zero_length_secitem) {
166 unicodeToItem(password.c_str(), &unicodePw); 171 unicodeToItem(password.c_str(), &unicodePw);
167 } 172 }
168 173
169 // Initialize the decoder 174 // Initialize the decoder
170 dcx = SEC_PKCS12DecoderStart(&unicodePw, slot, 175 dcx = SEC_PKCS12DecoderStart(&unicodePw, slot,
171 // wincx 176 // wincx
172 NULL, 177 NULL,
173 // dOpen, dClose, dRead, dWrite, dArg: NULL 178 // dOpen, dClose, dRead, dWrite, dArg: NULL
174 // specifies default impl using memory buffer. 179 // specifies default impl using memory buffer.
175 NULL, NULL, NULL, NULL, NULL); 180 NULL, NULL, NULL, NULL, NULL);
176 if (!dcx) { 181 if (!dcx) {
177 srv = SECFailure; 182 srv = SECFailure;
178 goto finish; 183 goto finish;
179 } 184 }
180 // feed input to the decoder 185 // feed input to the decoder
181 srv = SEC_PKCS12DecoderUpdate(dcx, 186 srv = SEC_PKCS12DecoderUpdate(dcx,
182 (unsigned char*)pkcs12_data, 187 (unsigned char*)pkcs12_data,
183 pkcs12_len); 188 pkcs12_len);
184 if (srv) goto finish; 189 if (srv) goto finish;
185 // verify the blob 190 // verify the blob
186 srv = SEC_PKCS12DecoderVerify(dcx); 191 srv = SEC_PKCS12DecoderVerify(dcx);
187 if (srv) goto finish; 192 if (srv) goto finish;
188 // validate bags 193 // validate bags
189 srv = SEC_PKCS12DecoderValidateBags(dcx, nickname_collision); 194 srv = SEC_PKCS12DecoderValidateBags(dcx, nickname_collision);
190 if (srv) goto finish; 195 if (srv) goto finish;
191 // import cert and key 196 // import certificate and key
192 srv = SEC_PKCS12DecoderImportBags(dcx); 197 srv = SEC_PKCS12DecoderImportBags(dcx);
193 if (srv) goto finish; 198 if (srv) goto finish;
194 199
195 if (!is_extractable) { 200 attribute_value.data = &attribute_data;
196 SECItem attribute_value; 201 attribute_value.len = sizeof(attribute_data);
197 CK_BBOOL attribute_data = CK_FALSE;
198 attribute_value.data = &attribute_data;
199 attribute_value.len = sizeof(attribute_data);
200 202
201 srv = SEC_PKCS12DecoderIterateInit(dcx); 203 srv = SEC_PKCS12DecoderIterateInit(dcx);
202 if (srv) goto finish; 204 if (srv) goto finish;
203 205
204 const SEC_PKCS12DecoderItem* decoder_item = NULL; 206 if (imported_certs)
207 imported_certs->clear();
208
209 // Collect the list of decoded certificates, and mark private keys
210 // non-extractable if needed.
211 while (SEC_PKCS12DecoderIterateNext(dcx, &decoder_item) == SECSuccess) {
212 if (decoder_item->type != SEC_OID_PKCS12_V1_CERT_BAG_ID)
213 continue;
214 if (!decoder_item->hasKey)
215 continue;
wtc 2011/11/29 23:13:57 BUG: I would expect that a certificate without a c
Greg Spencer (Chromium) 2011/12/02 18:50:07 Oooh. Nice catch. Done.
216
217 // Once we have determined that the imported certificate has an
218 // associated private key too, only then can we mark the key as
219 // non-extractable.
220 CERTCertificate* cert = PK11_FindCertFromDERCertItem(
221 slot, decoder_item->der,
222 NULL); // wincx
223 if (!cert) {
224 LOG(ERROR) << "Could not grab a handle to the certificate in the slot "
225 << "from the corresponding PKCS#12 DER certificate.";
226 continue;
227 }
228
229 // Add the cert to the list
230 if (imported_certs) {
231 // Empty list of intermediates.
232 net::X509Certificate::OSCertHandles intermediates;
233 imported_certs->push_back(
234 net::X509Certificate::CreateFromHandle(cert, intermediates));
235 }
236
205 // Iterate through all the imported PKCS12 items and mark any accompanying 237 // Iterate through all the imported PKCS12 items and mark any accompanying
206 // private keys as unextractable. 238 // private keys as non-extractable.
207 while (SEC_PKCS12DecoderIterateNext(dcx, &decoder_item) == SECSuccess) { 239 if (!is_extractable) {
208 if (decoder_item->type != SEC_OID_PKCS12_V1_CERT_BAG_ID)
209 continue;
210 if (!decoder_item->hasKey)
211 continue;
212
213 // Once we have determined that the imported certificate has an
214 // associated private key too, only then can we mark the key as
215 // unextractable.
216 CERTCertificate* cert = PK11_FindCertFromDERCertItem(
217 slot, decoder_item->der,
218 NULL); // wincx
219 if (!cert) {
220 LOG(ERROR) << "Could not grab a handle to the certificate in the slot "
221 << "from the corresponding PKCS#12 DER certificate.";
222 continue;
223 }
224 SECKEYPrivateKey* privKey = PK11_FindPrivateKeyFromCert(slot, cert, 240 SECKEYPrivateKey* privKey = PK11_FindPrivateKeyFromCert(slot, cert,
225 NULL); // wincx 241 NULL); // wincx
226 CERT_DestroyCertificate(cert);
227 if (privKey) { 242 if (privKey) {
228 // Mark the private key as unextractable. 243 // Mark the private key as non-extractable.
229 srv = PK11_WriteRawAttribute(PK11_TypePrivKey, privKey, CKA_EXTRACTABLE, 244 srv = PK11_WriteRawAttribute(PK11_TypePrivKey, privKey, CKA_EXTRACTABLE,
230 &attribute_value); 245 &attribute_value);
231 SECKEY_DestroyPrivateKey(privKey); 246 SECKEY_DestroyPrivateKey(privKey);
232 if (srv) { 247 if (srv) {
233 LOG(ERROR) << "Could not set CKA_EXTRACTABLE attribute on private " 248 LOG(ERROR) << "Could not set CKA_EXTRACTABLE attribute on private "
234 << "key."; 249 << "key.";
250 CERT_DestroyCertificate(cert);
235 break; 251 break;
236 } 252 }
237 } 253 }
238 } 254 }
255 CERT_DestroyCertificate(cert);
239 if (srv) goto finish; 256 if (srv) goto finish;
240 } 257 }
241
242 import_result = net::OK; 258 import_result = net::OK;
243 finish: 259 finish:
244 // If srv != SECSuccess, NSS probably set a specific error code. 260 // If srv != SECSuccess, NSS probably set a specific error code.
245 // We should use that error code instead of inventing a new one 261 // We should use that error code instead of inventing a new one
246 // for every error possible. 262 // for every error possible.
247 if (srv != SECSuccess) { 263 if (srv != SECSuccess) {
248 int error = PORT_GetError(); 264 int error = PORT_GetError();
249 LOG(ERROR) << "PKCS#12 import failed with error " << error; 265 LOG(ERROR) << "PKCS#12 import failed with error " << error;
250 switch (error) { 266 switch (error) {
251 case SEC_ERROR_BAD_PASSWORD: 267 case SEC_ERROR_BAD_PASSWORD:
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
328 344
329 void EnsurePKCS12Init() { 345 void EnsurePKCS12Init() {
330 g_pkcs12_init_singleton.Get(); 346 g_pkcs12_init_singleton.Get();
331 } 347 }
332 348
333 // Based on nsPKCS12Blob::ImportFromFile. 349 // Based on nsPKCS12Blob::ImportFromFile.
334 int nsPKCS12Blob_Import(PK11SlotInfo* slot, 350 int nsPKCS12Blob_Import(PK11SlotInfo* slot,
335 const char* pkcs12_data, 351 const char* pkcs12_data,
336 size_t pkcs12_len, 352 size_t pkcs12_len,
337 const string16& password, 353 const string16& password,
338 bool is_extractable) { 354 bool is_extractable,
355 net::CertificateList* imported_certs) {
339 356
340 int rv = nsPKCS12Blob_ImportHelper(pkcs12_data, pkcs12_len, password, 357 int rv = nsPKCS12Blob_ImportHelper(pkcs12_data, pkcs12_len, password,
341 is_extractable, false, slot); 358 is_extractable, false, slot,
359 imported_certs);
342 360
343 // When the user entered a zero length password: 361 // When the user entered a zero length password:
344 // An empty password should be represented as an empty 362 // An empty password should be represented as an empty
345 // string (a SECItem that contains a single terminating 363 // string (a SECItem that contains a single terminating
346 // NULL UTF16 character), but some applications use a 364 // NULL UTF16 character), but some applications use a
347 // zero length SECItem. 365 // zero length SECItem.
348 // We try both variations, zero length item and empty string, 366 // We try both variations, zero length item and empty string,
349 // without giving a user prompt when trying the different empty password 367 // without giving a user prompt when trying the different empty password
350 // flavors. 368 // flavors.
351 if (rv == net::ERR_PKCS12_IMPORT_BAD_PASSWORD && password.empty()) { 369 if (rv == net::ERR_PKCS12_IMPORT_BAD_PASSWORD && password.empty()) {
352 rv = nsPKCS12Blob_ImportHelper(pkcs12_data, pkcs12_len, password, 370 rv = nsPKCS12Blob_ImportHelper(pkcs12_data, pkcs12_len, password,
353 is_extractable, true, slot); 371 is_extractable, true, slot, imported_certs);
354 } 372 }
355 return rv; 373 return rv;
356 } 374 }
357 375
358 // Based on nsPKCS12Blob::ExportToFile 376 // Based on nsPKCS12Blob::ExportToFile
359 // 377 //
360 // Having already loaded the certs, form them into a blob (loading the keys 378 // Having already loaded the certs, form them into a blob (loading the keys
361 // also), encode the blob, and stuff it into the file. 379 // also), encode the blob, and stuff it into the file.
362 // 380 //
363 // TODO: handle slots correctly 381 // TODO: handle slots correctly
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after
456 finish: 474 finish:
457 if (srv) 475 if (srv)
458 LOG(ERROR) << "PKCS#12 export failed with error " << PORT_GetError(); 476 LOG(ERROR) << "PKCS#12 export failed with error " << PORT_GetError();
459 if (ecx) 477 if (ecx)
460 SEC_PKCS12DestroyExportContext(ecx); 478 SEC_PKCS12DestroyExportContext(ecx);
461 SECITEM_ZfreeItem(&unicodePw, PR_FALSE); 479 SECITEM_ZfreeItem(&unicodePw, PR_FALSE);
462 return return_count; 480 return return_count;
463 } 481 }
464 482
465 } // namespace mozilla_security_manager 483 } // namespace mozilla_security_manager
OLDNEW
« net/base/x509_certificate_nss.cc ('K') | « net/third_party/mozilla_security_manager/nsPKCS12Blob.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698