|
1 /* -*- Mode: C; tab-width: 8 -*-*/ |
|
2 /* This Source Code Form is subject to the terms of the Mozilla Public |
|
3 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
5 |
|
6 #include "crmf.h" |
|
7 #include "crmfi.h" |
|
8 #include "pk11func.h" |
|
9 #include "keyhi.h" |
|
10 #include "secoid.h" |
|
11 |
|
12 static SECStatus |
|
13 crmf_modify_control_array (CRMFCertRequest *inCertReq, int count) |
|
14 { |
|
15 if (count > 0) { |
|
16 void *dummy = PORT_Realloc(inCertReq->controls, |
|
17 sizeof(CRMFControl*)*(count+2)); |
|
18 if (dummy == NULL) { |
|
19 return SECFailure; |
|
20 } |
|
21 inCertReq->controls = dummy; |
|
22 } else { |
|
23 inCertReq->controls = PORT_ZNewArray(CRMFControl*, 2); |
|
24 } |
|
25 return (inCertReq->controls == NULL) ? SECFailure : SECSuccess ; |
|
26 } |
|
27 |
|
28 static SECStatus |
|
29 crmf_add_new_control(CRMFCertRequest *inCertReq,SECOidTag inTag, |
|
30 CRMFControl **destControl) |
|
31 { |
|
32 SECOidData *oidData; |
|
33 SECStatus rv; |
|
34 PLArenaPool *poolp; |
|
35 int numControls = 0; |
|
36 CRMFControl *newControl; |
|
37 CRMFControl **controls; |
|
38 void *mark; |
|
39 |
|
40 poolp = inCertReq->poolp; |
|
41 if (poolp == NULL) { |
|
42 return SECFailure; |
|
43 } |
|
44 mark = PORT_ArenaMark(poolp); |
|
45 if (inCertReq->controls != NULL) { |
|
46 while (inCertReq->controls[numControls] != NULL) |
|
47 numControls++; |
|
48 } |
|
49 rv = crmf_modify_control_array(inCertReq, numControls); |
|
50 if (rv != SECSuccess) { |
|
51 goto loser; |
|
52 } |
|
53 controls = inCertReq->controls; |
|
54 oidData = SECOID_FindOIDByTag(inTag); |
|
55 newControl = *destControl = PORT_ArenaZNew(poolp,CRMFControl); |
|
56 if (newControl == NULL) { |
|
57 goto loser; |
|
58 } |
|
59 rv = SECITEM_CopyItem(poolp, &newControl->derTag, &oidData->oid); |
|
60 if (rv != SECSuccess) { |
|
61 goto loser; |
|
62 } |
|
63 newControl->tag = inTag; |
|
64 controls[numControls] = newControl; |
|
65 controls[numControls+1] = NULL; |
|
66 PORT_ArenaUnmark(poolp, mark); |
|
67 return SECSuccess; |
|
68 |
|
69 loser: |
|
70 PORT_ArenaRelease(poolp, mark); |
|
71 *destControl = NULL; |
|
72 return SECFailure; |
|
73 |
|
74 } |
|
75 |
|
76 static SECStatus |
|
77 crmf_add_secitem_control(CRMFCertRequest *inCertReq, SECItem *value, |
|
78 SECOidTag inTag) |
|
79 { |
|
80 SECStatus rv; |
|
81 CRMFControl *newControl; |
|
82 void *mark; |
|
83 |
|
84 rv = crmf_add_new_control(inCertReq, inTag, &newControl); |
|
85 if (rv != SECSuccess) { |
|
86 return rv; |
|
87 } |
|
88 mark = PORT_ArenaMark(inCertReq->poolp); |
|
89 rv = SECITEM_CopyItem(inCertReq->poolp, &newControl->derValue, value); |
|
90 if (rv != SECSuccess) { |
|
91 PORT_ArenaRelease(inCertReq->poolp, mark); |
|
92 return rv; |
|
93 } |
|
94 PORT_ArenaUnmark(inCertReq->poolp, mark); |
|
95 return SECSuccess; |
|
96 } |
|
97 |
|
98 SECStatus |
|
99 CRMF_CertRequestSetRegTokenControl(CRMFCertRequest *inCertReq, SECItem *value) |
|
100 { |
|
101 return crmf_add_secitem_control(inCertReq, value, |
|
102 SEC_OID_PKIX_REGCTRL_REGTOKEN); |
|
103 } |
|
104 |
|
105 SECStatus |
|
106 CRMF_CertRequestSetAuthenticatorControl (CRMFCertRequest *inCertReq, |
|
107 SECItem *value) |
|
108 { |
|
109 return crmf_add_secitem_control(inCertReq, value, |
|
110 SEC_OID_PKIX_REGCTRL_AUTHENTICATOR); |
|
111 } |
|
112 |
|
113 SECStatus |
|
114 crmf_destroy_encrypted_value(CRMFEncryptedValue *inEncrValue, PRBool freeit) |
|
115 { |
|
116 if (inEncrValue != NULL) { |
|
117 if (inEncrValue->intendedAlg) { |
|
118 SECOID_DestroyAlgorithmID(inEncrValue->intendedAlg, PR_TRUE); |
|
119 inEncrValue->intendedAlg = NULL; |
|
120 } |
|
121 if (inEncrValue->symmAlg) { |
|
122 SECOID_DestroyAlgorithmID(inEncrValue->symmAlg, PR_TRUE); |
|
123 inEncrValue->symmAlg = NULL; |
|
124 } |
|
125 if (inEncrValue->encSymmKey.data) { |
|
126 PORT_Free(inEncrValue->encSymmKey.data); |
|
127 inEncrValue->encSymmKey.data = NULL; |
|
128 } |
|
129 if (inEncrValue->keyAlg) { |
|
130 SECOID_DestroyAlgorithmID(inEncrValue->keyAlg, PR_TRUE); |
|
131 inEncrValue->keyAlg = NULL; |
|
132 } |
|
133 if (inEncrValue->valueHint.data) { |
|
134 PORT_Free(inEncrValue->valueHint.data); |
|
135 inEncrValue->valueHint.data = NULL; |
|
136 } |
|
137 if (inEncrValue->encValue.data) { |
|
138 PORT_Free(inEncrValue->encValue.data); |
|
139 inEncrValue->encValue.data = NULL; |
|
140 } |
|
141 if (freeit) { |
|
142 PORT_Free(inEncrValue); |
|
143 } |
|
144 } |
|
145 return SECSuccess; |
|
146 } |
|
147 |
|
148 SECStatus |
|
149 CRMF_DestroyEncryptedValue(CRMFEncryptedValue *inEncrValue) |
|
150 { |
|
151 return crmf_destroy_encrypted_value(inEncrValue, PR_TRUE); |
|
152 } |
|
153 |
|
154 SECStatus |
|
155 crmf_copy_encryptedvalue_secalg(PLArenaPool *poolp, |
|
156 SECAlgorithmID *srcAlgId, |
|
157 SECAlgorithmID **destAlgId) |
|
158 { |
|
159 SECAlgorithmID *newAlgId; |
|
160 SECStatus rv; |
|
161 |
|
162 newAlgId = (poolp != NULL) ? PORT_ArenaZNew(poolp, SECAlgorithmID) : |
|
163 PORT_ZNew(SECAlgorithmID); |
|
164 if (newAlgId == NULL) { |
|
165 return SECFailure; |
|
166 } |
|
167 |
|
168 rv = SECOID_CopyAlgorithmID(poolp, newAlgId, srcAlgId); |
|
169 if (rv != SECSuccess) { |
|
170 if (!poolp) { |
|
171 SECOID_DestroyAlgorithmID(newAlgId, PR_TRUE); |
|
172 } |
|
173 return rv; |
|
174 } |
|
175 *destAlgId = newAlgId; |
|
176 |
|
177 return rv; |
|
178 } |
|
179 |
|
180 SECStatus |
|
181 crmf_copy_encryptedvalue(PLArenaPool *poolp, |
|
182 CRMFEncryptedValue *srcValue, |
|
183 CRMFEncryptedValue *destValue) |
|
184 { |
|
185 SECStatus rv; |
|
186 |
|
187 if (srcValue->intendedAlg != NULL) { |
|
188 rv = crmf_copy_encryptedvalue_secalg(poolp, |
|
189 srcValue->intendedAlg, |
|
190 &destValue->intendedAlg); |
|
191 if (rv != SECSuccess) { |
|
192 goto loser; |
|
193 } |
|
194 } |
|
195 if (srcValue->symmAlg != NULL) { |
|
196 rv = crmf_copy_encryptedvalue_secalg(poolp, |
|
197 srcValue->symmAlg, |
|
198 &destValue->symmAlg); |
|
199 if (rv != SECSuccess) { |
|
200 goto loser; |
|
201 } |
|
202 } |
|
203 if (srcValue->encSymmKey.data != NULL) { |
|
204 rv = crmf_make_bitstring_copy(poolp, |
|
205 &destValue->encSymmKey, |
|
206 &srcValue->encSymmKey); |
|
207 if (rv != SECSuccess) { |
|
208 goto loser; |
|
209 } |
|
210 } |
|
211 if (srcValue->keyAlg != NULL) { |
|
212 rv = crmf_copy_encryptedvalue_secalg(poolp, |
|
213 srcValue->keyAlg, |
|
214 &destValue->keyAlg); |
|
215 if (rv != SECSuccess) { |
|
216 goto loser; |
|
217 } |
|
218 } |
|
219 if (srcValue->valueHint.data != NULL) { |
|
220 rv = SECITEM_CopyItem(poolp, |
|
221 &destValue->valueHint, |
|
222 &srcValue->valueHint); |
|
223 if (rv != SECSuccess) { |
|
224 goto loser; |
|
225 } |
|
226 } |
|
227 if (srcValue->encValue.data != NULL) { |
|
228 rv = crmf_make_bitstring_copy(poolp, |
|
229 &destValue->encValue, |
|
230 &srcValue->encValue); |
|
231 if (rv != SECSuccess) { |
|
232 goto loser; |
|
233 } |
|
234 } |
|
235 return SECSuccess; |
|
236 loser: |
|
237 if (poolp == NULL && destValue != NULL) { |
|
238 crmf_destroy_encrypted_value(destValue, PR_FALSE); |
|
239 } |
|
240 return SECFailure; |
|
241 } |
|
242 |
|
243 SECStatus |
|
244 crmf_copy_encryptedkey(PLArenaPool *poolp, |
|
245 CRMFEncryptedKey *srcEncrKey, |
|
246 CRMFEncryptedKey *destEncrKey) |
|
247 { |
|
248 SECStatus rv; |
|
249 void *mark = NULL; |
|
250 |
|
251 if (poolp != NULL) { |
|
252 mark = PORT_ArenaMark(poolp); |
|
253 } |
|
254 |
|
255 switch (srcEncrKey->encKeyChoice) { |
|
256 case crmfEncryptedValueChoice: |
|
257 rv = crmf_copy_encryptedvalue(poolp, |
|
258 &srcEncrKey->value.encryptedValue, |
|
259 &destEncrKey->value.encryptedValue); |
|
260 break; |
|
261 case crmfEnvelopedDataChoice: |
|
262 destEncrKey->value.envelopedData = |
|
263 SEC_PKCS7CopyContentInfo(srcEncrKey->value.envelopedData); |
|
264 rv = (destEncrKey->value.envelopedData != NULL) ? SECSuccess: |
|
265 SECFailure; |
|
266 break; |
|
267 default: |
|
268 rv = SECFailure; |
|
269 } |
|
270 if (rv != SECSuccess) { |
|
271 goto loser; |
|
272 } |
|
273 destEncrKey->encKeyChoice = srcEncrKey->encKeyChoice; |
|
274 if (mark) { |
|
275 PORT_ArenaUnmark(poolp, mark); |
|
276 } |
|
277 return SECSuccess; |
|
278 |
|
279 loser: |
|
280 if (mark) { |
|
281 PORT_ArenaRelease(poolp, mark); |
|
282 } |
|
283 return SECFailure; |
|
284 } |
|
285 |
|
286 static CRMFPKIArchiveOptions* |
|
287 crmf_create_encr_pivkey_option(CRMFEncryptedKey *inEncryptedKey) |
|
288 { |
|
289 CRMFPKIArchiveOptions *newArchOpt; |
|
290 SECStatus rv; |
|
291 |
|
292 newArchOpt = PORT_ZNew(CRMFPKIArchiveOptions); |
|
293 if (newArchOpt == NULL) { |
|
294 goto loser; |
|
295 } |
|
296 |
|
297 rv = crmf_copy_encryptedkey(NULL, inEncryptedKey, |
|
298 &newArchOpt->option.encryptedKey); |
|
299 |
|
300 if (rv != SECSuccess) { |
|
301 goto loser; |
|
302 } |
|
303 newArchOpt->archOption = crmfEncryptedPrivateKey; |
|
304 return newArchOpt; |
|
305 loser: |
|
306 if (newArchOpt != NULL) { |
|
307 CRMF_DestroyPKIArchiveOptions(newArchOpt); |
|
308 } |
|
309 return NULL; |
|
310 } |
|
311 |
|
312 static CRMFPKIArchiveOptions* |
|
313 crmf_create_keygen_param_option(SECItem *inKeyGenParams) |
|
314 { |
|
315 CRMFPKIArchiveOptions *newArchOptions; |
|
316 SECStatus rv; |
|
317 |
|
318 newArchOptions = PORT_ZNew(CRMFPKIArchiveOptions); |
|
319 if (newArchOptions == NULL) { |
|
320 goto loser; |
|
321 } |
|
322 newArchOptions->archOption = crmfKeyGenParameters; |
|
323 rv = SECITEM_CopyItem(NULL, &newArchOptions->option.keyGenParameters, |
|
324 inKeyGenParams); |
|
325 if (rv != SECSuccess) { |
|
326 goto loser; |
|
327 } |
|
328 return newArchOptions; |
|
329 loser: |
|
330 if (newArchOptions != NULL) { |
|
331 CRMF_DestroyPKIArchiveOptions(newArchOptions); |
|
332 } |
|
333 return NULL; |
|
334 } |
|
335 |
|
336 static CRMFPKIArchiveOptions* |
|
337 crmf_create_arch_rem_gen_privkey(PRBool archiveRemGenPrivKey) |
|
338 { |
|
339 unsigned char value; |
|
340 SECItem *dummy; |
|
341 CRMFPKIArchiveOptions *newArchOptions; |
|
342 |
|
343 value = (archiveRemGenPrivKey) ? hexTrue : hexFalse; |
|
344 newArchOptions = PORT_ZNew(CRMFPKIArchiveOptions); |
|
345 if (newArchOptions == NULL) { |
|
346 goto loser; |
|
347 } |
|
348 dummy = SEC_ASN1EncodeItem(NULL, |
|
349 &newArchOptions->option.archiveRemGenPrivKey, |
|
350 &value, SEC_ASN1_GET(SEC_BooleanTemplate)); |
|
351 PORT_Assert (dummy == &newArchOptions->option.archiveRemGenPrivKey); |
|
352 if (dummy != &newArchOptions->option.archiveRemGenPrivKey) { |
|
353 SECITEM_FreeItem (dummy, PR_TRUE); |
|
354 goto loser; |
|
355 } |
|
356 newArchOptions->archOption = crmfArchiveRemGenPrivKey; |
|
357 return newArchOptions; |
|
358 loser: |
|
359 if (newArchOptions != NULL) { |
|
360 CRMF_DestroyPKIArchiveOptions(newArchOptions); |
|
361 } |
|
362 return NULL; |
|
363 } |
|
364 |
|
365 CRMFPKIArchiveOptions* |
|
366 CRMF_CreatePKIArchiveOptions(CRMFPKIArchiveOptionsType inType, void *data) |
|
367 { |
|
368 CRMFPKIArchiveOptions* retOptions; |
|
369 |
|
370 PORT_Assert(data != NULL); |
|
371 if (data == NULL) { |
|
372 return NULL; |
|
373 } |
|
374 switch(inType) { |
|
375 case crmfEncryptedPrivateKey: |
|
376 retOptions = crmf_create_encr_pivkey_option((CRMFEncryptedKey*)data); |
|
377 break; |
|
378 case crmfKeyGenParameters: |
|
379 retOptions = crmf_create_keygen_param_option((SECItem*)data); |
|
380 break; |
|
381 case crmfArchiveRemGenPrivKey: |
|
382 retOptions = crmf_create_arch_rem_gen_privkey(*(PRBool*)data); |
|
383 break; |
|
384 default: |
|
385 retOptions = NULL; |
|
386 } |
|
387 return retOptions; |
|
388 } |
|
389 |
|
390 static SECStatus |
|
391 crmf_destroy_encrypted_key(CRMFEncryptedKey *inEncrKey, PRBool freeit) |
|
392 { |
|
393 PORT_Assert(inEncrKey != NULL); |
|
394 if (inEncrKey != NULL) { |
|
395 switch (inEncrKey->encKeyChoice){ |
|
396 case crmfEncryptedValueChoice: |
|
397 crmf_destroy_encrypted_value(&inEncrKey->value.encryptedValue, |
|
398 PR_FALSE); |
|
399 break; |
|
400 case crmfEnvelopedDataChoice: |
|
401 SEC_PKCS7DestroyContentInfo(inEncrKey->value.envelopedData); |
|
402 break; |
|
403 default: |
|
404 break; |
|
405 } |
|
406 if (freeit) { |
|
407 PORT_Free(inEncrKey); |
|
408 } |
|
409 } |
|
410 return SECSuccess; |
|
411 } |
|
412 |
|
413 SECStatus |
|
414 crmf_destroy_pkiarchiveoptions(CRMFPKIArchiveOptions *inArchOptions, |
|
415 PRBool freeit) |
|
416 { |
|
417 PORT_Assert(inArchOptions != NULL); |
|
418 if (inArchOptions != NULL) { |
|
419 switch (inArchOptions->archOption) { |
|
420 case crmfEncryptedPrivateKey: |
|
421 crmf_destroy_encrypted_key(&inArchOptions->option.encryptedKey, |
|
422 PR_FALSE); |
|
423 break; |
|
424 case crmfKeyGenParameters: |
|
425 case crmfArchiveRemGenPrivKey: |
|
426 /* This is a union, so having a pointer to one is like |
|
427 * having a pointer to both. |
|
428 */ |
|
429 SECITEM_FreeItem(&inArchOptions->option.keyGenParameters, |
|
430 PR_FALSE); |
|
431 break; |
|
432 case crmfNoArchiveOptions: |
|
433 break; |
|
434 } |
|
435 if (freeit) { |
|
436 PORT_Free(inArchOptions); |
|
437 } |
|
438 } |
|
439 return SECSuccess; |
|
440 } |
|
441 |
|
442 SECStatus |
|
443 CRMF_DestroyPKIArchiveOptions(CRMFPKIArchiveOptions *inArchOptions) |
|
444 { |
|
445 return crmf_destroy_pkiarchiveoptions(inArchOptions, PR_TRUE); |
|
446 } |
|
447 |
|
448 static CK_MECHANISM_TYPE |
|
449 crmf_get_non_pad_mechanism(CK_MECHANISM_TYPE type) |
|
450 { |
|
451 switch (type) { |
|
452 case CKM_DES3_CBC_PAD: |
|
453 return CKM_DES3_CBC; |
|
454 case CKM_CAST5_CBC_PAD: |
|
455 return CKM_CAST5_CBC; |
|
456 case CKM_DES_CBC_PAD: |
|
457 return CKM_DES_CBC; |
|
458 case CKM_IDEA_CBC_PAD: |
|
459 return CKM_IDEA_CBC; |
|
460 case CKM_CAST3_CBC_PAD: |
|
461 return CKM_CAST3_CBC; |
|
462 case CKM_CAST_CBC_PAD: |
|
463 return CKM_CAST_CBC; |
|
464 case CKM_RC5_CBC_PAD: |
|
465 return CKM_RC5_CBC; |
|
466 case CKM_RC2_CBC_PAD: |
|
467 return CKM_RC2_CBC; |
|
468 case CKM_CDMF_CBC_PAD: |
|
469 return CKM_CDMF_CBC; |
|
470 } |
|
471 return type; |
|
472 } |
|
473 |
|
474 static CK_MECHANISM_TYPE |
|
475 crmf_get_pad_mech_from_tag(SECOidTag oidTag) |
|
476 { |
|
477 CK_MECHANISM_TYPE mechType; |
|
478 SECOidData *oidData; |
|
479 |
|
480 oidData = SECOID_FindOIDByTag(oidTag); |
|
481 mechType = (CK_MECHANISM_TYPE)oidData->mechanism; |
|
482 return PK11_GetPadMechanism(mechType); |
|
483 } |
|
484 |
|
485 static CK_MECHANISM_TYPE |
|
486 crmf_get_best_privkey_wrap_mechanism(PK11SlotInfo *slot) |
|
487 { |
|
488 CK_MECHANISM_TYPE privKeyPadMechs[] = { CKM_DES3_CBC_PAD, |
|
489 CKM_CAST5_CBC_PAD, |
|
490 CKM_DES_CBC_PAD, |
|
491 CKM_IDEA_CBC_PAD, |
|
492 CKM_CAST3_CBC_PAD, |
|
493 CKM_CAST_CBC_PAD, |
|
494 CKM_RC5_CBC_PAD, |
|
495 CKM_RC2_CBC_PAD, |
|
496 CKM_CDMF_CBC_PAD }; |
|
497 int mechCount = sizeof(privKeyPadMechs)/sizeof(privKeyPadMechs[0]); |
|
498 int i; |
|
499 |
|
500 for (i=0; i < mechCount; i++) { |
|
501 if (PK11_DoesMechanism(slot, privKeyPadMechs[i])) { |
|
502 return privKeyPadMechs[i]; |
|
503 } |
|
504 } |
|
505 return CKM_INVALID_MECHANISM; |
|
506 } |
|
507 |
|
508 CK_MECHANISM_TYPE |
|
509 CRMF_GetBestWrapPadMechanism(PK11SlotInfo *slot) |
|
510 { |
|
511 return crmf_get_best_privkey_wrap_mechanism(slot); |
|
512 } |
|
513 |
|
514 static SECItem* |
|
515 crmf_get_iv(CK_MECHANISM_TYPE mechType) |
|
516 { |
|
517 int iv_size = PK11_GetIVLength(mechType); |
|
518 SECItem *iv; |
|
519 SECStatus rv; |
|
520 |
|
521 iv = PORT_ZNew(SECItem); |
|
522 if (iv == NULL) { |
|
523 return NULL; |
|
524 } |
|
525 if (iv_size == 0) { |
|
526 iv->data = NULL; |
|
527 iv->len = 0; |
|
528 return iv; |
|
529 } |
|
530 iv->data = PORT_NewArray(unsigned char, iv_size); |
|
531 if (iv->data == NULL) { |
|
532 iv->len = 0; |
|
533 return iv; |
|
534 } |
|
535 iv->len = iv_size; |
|
536 rv = PK11_GenerateRandom(iv->data, iv->len); |
|
537 if (rv != SECSuccess) { |
|
538 PORT_Free(iv->data); |
|
539 iv->data = NULL; |
|
540 iv->len = 0; |
|
541 } |
|
542 return iv; |
|
543 } |
|
544 |
|
545 SECItem* |
|
546 CRMF_GetIVFromMechanism(CK_MECHANISM_TYPE mechType) |
|
547 { |
|
548 return crmf_get_iv(mechType); |
|
549 } |
|
550 |
|
551 CK_MECHANISM_TYPE |
|
552 crmf_get_mechanism_from_public_key(SECKEYPublicKey *inPubKey) |
|
553 { |
|
554 CERTSubjectPublicKeyInfo *spki = NULL; |
|
555 SECOidTag tag; |
|
556 |
|
557 |
|
558 spki = SECKEY_CreateSubjectPublicKeyInfo(inPubKey); |
|
559 if (spki == NULL) { |
|
560 return CKM_INVALID_MECHANISM; |
|
561 } |
|
562 tag = SECOID_FindOIDTag(&spki->algorithm.algorithm); |
|
563 SECKEY_DestroySubjectPublicKeyInfo(spki); |
|
564 spki = NULL; |
|
565 return PK11_AlgtagToMechanism(tag); |
|
566 } |
|
567 |
|
568 SECItem* |
|
569 crmf_get_public_value(SECKEYPublicKey *pubKey, SECItem *dest) |
|
570 { |
|
571 SECItem *src; |
|
572 |
|
573 switch(pubKey->keyType) { |
|
574 case dsaKey: |
|
575 src = &pubKey->u.dsa.publicValue; |
|
576 break; |
|
577 case rsaKey: |
|
578 src = &pubKey->u.rsa.modulus; |
|
579 break; |
|
580 case dhKey: |
|
581 src = &pubKey->u.dh.publicValue; |
|
582 break; |
|
583 default: |
|
584 src = NULL; |
|
585 break; |
|
586 } |
|
587 if (!src) { |
|
588 PORT_SetError(SEC_ERROR_INVALID_ARGS); |
|
589 return NULL; |
|
590 } |
|
591 |
|
592 if (dest != NULL) { |
|
593 SECStatus rv = SECITEM_CopyItem(NULL, dest, src); |
|
594 if (rv != SECSuccess) { |
|
595 dest = NULL; |
|
596 } |
|
597 } else { |
|
598 dest = SECITEM_ArenaDupItem(NULL, src); |
|
599 } |
|
600 return dest; |
|
601 } |
|
602 |
|
603 static SECItem* |
|
604 crmf_decode_params(SECItem *inParams) |
|
605 { |
|
606 SECItem *params; |
|
607 SECStatus rv = SECFailure; |
|
608 PLArenaPool *poolp; |
|
609 |
|
610 poolp = PORT_NewArena(CRMF_DEFAULT_ARENA_SIZE); |
|
611 if (poolp == NULL) { |
|
612 return NULL; |
|
613 } |
|
614 |
|
615 params = PORT_ArenaZNew(poolp, SECItem); |
|
616 if (params) { |
|
617 rv = SEC_ASN1DecodeItem(poolp, params, |
|
618 SEC_ASN1_GET(SEC_OctetStringTemplate), |
|
619 inParams); |
|
620 } |
|
621 params = (rv == SECSuccess) ? SECITEM_ArenaDupItem(NULL, params) : NULL; |
|
622 PORT_FreeArena(poolp, PR_FALSE); |
|
623 return params; |
|
624 } |
|
625 |
|
626 static int |
|
627 crmf_get_key_size_from_mech(CK_MECHANISM_TYPE mechType) |
|
628 { |
|
629 CK_MECHANISM_TYPE keyGen = PK11_GetKeyGen(mechType); |
|
630 |
|
631 switch (keyGen) { |
|
632 case CKM_CDMF_KEY_GEN: |
|
633 case CKM_DES_KEY_GEN: |
|
634 return 8; |
|
635 case CKM_DES2_KEY_GEN: |
|
636 return 16; |
|
637 case CKM_DES3_KEY_GEN: |
|
638 return 24; |
|
639 } |
|
640 return 0; |
|
641 } |
|
642 |
|
643 SECStatus |
|
644 crmf_encrypted_value_unwrap_priv_key(PLArenaPool *poolp, |
|
645 CRMFEncryptedValue *encValue, |
|
646 SECKEYPrivateKey *privKey, |
|
647 SECKEYPublicKey *newPubKey, |
|
648 SECItem *nickname, |
|
649 PK11SlotInfo *slot, |
|
650 unsigned char keyUsage, |
|
651 SECKEYPrivateKey **unWrappedKey, |
|
652 void *wincx) |
|
653 { |
|
654 PK11SymKey *wrappingKey = NULL; |
|
655 CK_MECHANISM_TYPE wrapMechType; |
|
656 SECOidTag oidTag; |
|
657 SECItem *params = NULL, *publicValue = NULL; |
|
658 int keySize, origLen; |
|
659 CK_KEY_TYPE keyType; |
|
660 CK_ATTRIBUTE_TYPE *usage = NULL; |
|
661 CK_ATTRIBUTE_TYPE rsaUsage[] = { |
|
662 CKA_UNWRAP, CKA_DECRYPT, CKA_SIGN, CKA_SIGN_RECOVER }; |
|
663 CK_ATTRIBUTE_TYPE dsaUsage[] = { CKA_SIGN }; |
|
664 CK_ATTRIBUTE_TYPE dhUsage[] = { CKA_DERIVE }; |
|
665 int usageCount = 0; |
|
666 |
|
667 oidTag = SECOID_GetAlgorithmTag(encValue->symmAlg); |
|
668 wrapMechType = crmf_get_pad_mech_from_tag(oidTag); |
|
669 keySize = crmf_get_key_size_from_mech(wrapMechType); |
|
670 wrappingKey = PK11_PubUnwrapSymKey(privKey, &encValue->encSymmKey, |
|
671 wrapMechType, CKA_UNWRAP, keySize); |
|
672 if (wrappingKey == NULL) { |
|
673 goto loser; |
|
674 }/* Make the length a byte length instead of bit length*/ |
|
675 params = (encValue->symmAlg != NULL) ? |
|
676 crmf_decode_params(&encValue->symmAlg->parameters) : NULL; |
|
677 origLen = encValue->encValue.len; |
|
678 encValue->encValue.len = CRMF_BITS_TO_BYTES(origLen); |
|
679 publicValue = crmf_get_public_value(newPubKey, NULL); |
|
680 switch(newPubKey->keyType) { |
|
681 default: |
|
682 case rsaKey: |
|
683 keyType = CKK_RSA; |
|
684 switch (keyUsage & (KU_KEY_ENCIPHERMENT|KU_DIGITAL_SIGNATURE)) { |
|
685 case KU_KEY_ENCIPHERMENT: |
|
686 usage = rsaUsage; |
|
687 usageCount = 2; |
|
688 break; |
|
689 case KU_DIGITAL_SIGNATURE: |
|
690 usage = &rsaUsage[2]; |
|
691 usageCount = 2; |
|
692 break; |
|
693 case KU_KEY_ENCIPHERMENT|KU_DIGITAL_SIGNATURE: |
|
694 case 0: /* default to everything */ |
|
695 usage = rsaUsage; |
|
696 usageCount = 4; |
|
697 break; |
|
698 } |
|
699 break; |
|
700 case dhKey: |
|
701 keyType = CKK_DH; |
|
702 usage = dhUsage; |
|
703 usageCount = sizeof(dhUsage)/sizeof(dhUsage[0]); |
|
704 break; |
|
705 case dsaKey: |
|
706 keyType = CKK_DSA; |
|
707 usage = dsaUsage; |
|
708 usageCount = sizeof(dsaUsage)/sizeof(dsaUsage[0]); |
|
709 break; |
|
710 } |
|
711 PORT_Assert(usage != NULL); |
|
712 PORT_Assert(usageCount != 0); |
|
713 *unWrappedKey = PK11_UnwrapPrivKey(slot, wrappingKey, wrapMechType, params, |
|
714 &encValue->encValue, nickname, |
|
715 publicValue, PR_TRUE,PR_TRUE, |
|
716 keyType, usage, usageCount, wincx); |
|
717 encValue->encValue.len = origLen; |
|
718 if (*unWrappedKey == NULL) { |
|
719 goto loser; |
|
720 } |
|
721 SECITEM_FreeItem (publicValue, PR_TRUE); |
|
722 if (params!= NULL) { |
|
723 SECITEM_FreeItem(params, PR_TRUE); |
|
724 } |
|
725 PK11_FreeSymKey(wrappingKey); |
|
726 return SECSuccess; |
|
727 loser: |
|
728 *unWrappedKey = NULL; |
|
729 return SECFailure; |
|
730 } |
|
731 |
|
732 CRMFEncryptedValue * |
|
733 crmf_create_encrypted_value_wrapped_privkey(SECKEYPrivateKey *inPrivKey, |
|
734 SECKEYPublicKey *inCAKey, |
|
735 CRMFEncryptedValue *destValue) |
|
736 { |
|
737 SECItem wrappedPrivKey, wrappedSymKey; |
|
738 SECItem encodedParam, *dummy; |
|
739 SECStatus rv; |
|
740 CK_MECHANISM_TYPE pubMechType, symKeyType; |
|
741 unsigned char *wrappedSymKeyBits; |
|
742 unsigned char *wrappedPrivKeyBits; |
|
743 SECItem *iv = NULL; |
|
744 SECOidTag tag; |
|
745 PK11SymKey *symKey; |
|
746 PK11SlotInfo *slot; |
|
747 SECAlgorithmID *symmAlg; |
|
748 CRMFEncryptedValue *myEncrValue = NULL; |
|
749 |
|
750 encodedParam.data = NULL; |
|
751 wrappedSymKeyBits = PORT_NewArray(unsigned char, MAX_WRAPPED_KEY_LEN); |
|
752 wrappedPrivKeyBits = PORT_NewArray(unsigned char, MAX_WRAPPED_KEY_LEN); |
|
753 if (wrappedSymKeyBits == NULL || wrappedPrivKeyBits == NULL) { |
|
754 goto loser; |
|
755 } |
|
756 if (destValue == NULL) { |
|
757 myEncrValue = destValue = PORT_ZNew(CRMFEncryptedValue); |
|
758 if (destValue == NULL) { |
|
759 goto loser; |
|
760 } |
|
761 } |
|
762 |
|
763 pubMechType = crmf_get_mechanism_from_public_key(inCAKey); |
|
764 if (pubMechType == CKM_INVALID_MECHANISM) { |
|
765 /* XXX I should probably do something here for non-RSA |
|
766 * keys that are in certs. (ie DSA) |
|
767 * XXX or at least SET AN ERROR CODE. |
|
768 */ |
|
769 goto loser; |
|
770 } |
|
771 slot = inPrivKey->pkcs11Slot; |
|
772 PORT_Assert(slot != NULL); |
|
773 symKeyType = crmf_get_best_privkey_wrap_mechanism(slot); |
|
774 symKey = PK11_KeyGen(slot, symKeyType, NULL, 0, NULL); |
|
775 if (symKey == NULL) { |
|
776 goto loser; |
|
777 } |
|
778 |
|
779 wrappedSymKey.data = wrappedSymKeyBits; |
|
780 wrappedSymKey.len = MAX_WRAPPED_KEY_LEN; |
|
781 rv = PK11_PubWrapSymKey(pubMechType, inCAKey, symKey, &wrappedSymKey); |
|
782 if (rv != SECSuccess) { |
|
783 goto loser; |
|
784 } |
|
785 /* Make the length of the result a Bit String length. */ |
|
786 wrappedSymKey.len <<= 3; |
|
787 |
|
788 wrappedPrivKey.data = wrappedPrivKeyBits; |
|
789 wrappedPrivKey.len = MAX_WRAPPED_KEY_LEN; |
|
790 iv = crmf_get_iv(symKeyType); |
|
791 rv = PK11_WrapPrivKey(slot, symKey, inPrivKey, symKeyType, iv, |
|
792 &wrappedPrivKey, NULL); |
|
793 PK11_FreeSymKey(symKey); |
|
794 if (rv != SECSuccess) { |
|
795 goto loser; |
|
796 } |
|
797 /* Make the length of the result a Bit String length. */ |
|
798 wrappedPrivKey.len <<= 3; |
|
799 rv = crmf_make_bitstring_copy(NULL, |
|
800 &destValue->encValue, |
|
801 &wrappedPrivKey); |
|
802 if (rv != SECSuccess) { |
|
803 goto loser; |
|
804 } |
|
805 |
|
806 rv = crmf_make_bitstring_copy(NULL, |
|
807 &destValue->encSymmKey, |
|
808 &wrappedSymKey); |
|
809 if (rv != SECSuccess) { |
|
810 goto loser; |
|
811 } |
|
812 destValue->symmAlg = symmAlg = PORT_ZNew(SECAlgorithmID); |
|
813 if (symmAlg == NULL) { |
|
814 goto loser; |
|
815 } |
|
816 |
|
817 dummy = SEC_ASN1EncodeItem(NULL, &encodedParam, iv, |
|
818 SEC_ASN1_GET(SEC_OctetStringTemplate)); |
|
819 if (dummy != &encodedParam) { |
|
820 SECITEM_FreeItem(dummy, PR_TRUE); |
|
821 goto loser; |
|
822 } |
|
823 |
|
824 symKeyType = crmf_get_non_pad_mechanism(symKeyType); |
|
825 tag = PK11_MechanismToAlgtag(symKeyType); |
|
826 rv = SECOID_SetAlgorithmID(NULL, symmAlg, tag, &encodedParam); |
|
827 if (rv != SECSuccess) { |
|
828 goto loser; |
|
829 } |
|
830 SECITEM_FreeItem(&encodedParam, PR_FALSE); |
|
831 PORT_Free(wrappedPrivKeyBits); |
|
832 PORT_Free(wrappedSymKeyBits); |
|
833 SECITEM_FreeItem(iv, PR_TRUE); |
|
834 return destValue; |
|
835 loser: |
|
836 if (iv != NULL) { |
|
837 SECITEM_FreeItem(iv, PR_TRUE); |
|
838 } |
|
839 if (myEncrValue != NULL) { |
|
840 crmf_destroy_encrypted_value(myEncrValue, PR_TRUE); |
|
841 } |
|
842 if (wrappedSymKeyBits != NULL) { |
|
843 PORT_Free(wrappedSymKeyBits); |
|
844 } |
|
845 if (wrappedPrivKeyBits != NULL) { |
|
846 PORT_Free(wrappedPrivKeyBits); |
|
847 } |
|
848 if (encodedParam.data != NULL) { |
|
849 SECITEM_FreeItem(&encodedParam, PR_FALSE); |
|
850 } |
|
851 return NULL; |
|
852 } |
|
853 |
|
854 CRMFEncryptedKey* |
|
855 CRMF_CreateEncryptedKeyWithEncryptedValue (SECKEYPrivateKey *inPrivKey, |
|
856 CERTCertificate *inCACert) |
|
857 { |
|
858 SECKEYPublicKey *caPubKey = NULL; |
|
859 CRMFEncryptedKey *encKey = NULL; |
|
860 CRMFEncryptedValue *dummy; |
|
861 |
|
862 PORT_Assert(inPrivKey != NULL && inCACert != NULL); |
|
863 if (inPrivKey == NULL || inCACert == NULL) { |
|
864 return NULL; |
|
865 } |
|
866 |
|
867 caPubKey = CERT_ExtractPublicKey(inCACert); |
|
868 if (caPubKey == NULL) { |
|
869 goto loser; |
|
870 } |
|
871 |
|
872 encKey = PORT_ZNew(CRMFEncryptedKey); |
|
873 if (encKey == NULL) { |
|
874 goto loser; |
|
875 } |
|
876 dummy = crmf_create_encrypted_value_wrapped_privkey(inPrivKey, |
|
877 caPubKey, |
|
878 &encKey->value.encryptedValue); |
|
879 PORT_Assert(dummy == &encKey->value.encryptedValue); |
|
880 /* We won't add the der value here, but rather when it |
|
881 * becomes part of a certificate request. |
|
882 */ |
|
883 SECKEY_DestroyPublicKey(caPubKey); |
|
884 encKey->encKeyChoice = crmfEncryptedValueChoice; |
|
885 return encKey; |
|
886 loser: |
|
887 if (encKey != NULL) { |
|
888 CRMF_DestroyEncryptedKey(encKey); |
|
889 } |
|
890 if (caPubKey != NULL) { |
|
891 SECKEY_DestroyPublicKey(caPubKey); |
|
892 } |
|
893 return NULL; |
|
894 } |
|
895 |
|
896 SECStatus |
|
897 CRMF_DestroyEncryptedKey(CRMFEncryptedKey *inEncrKey) |
|
898 { |
|
899 return crmf_destroy_encrypted_key(inEncrKey, PR_TRUE); |
|
900 } |
|
901 |
|
902 SECStatus |
|
903 crmf_copy_pkiarchiveoptions(PLArenaPool *poolp, |
|
904 CRMFPKIArchiveOptions *destOpt, |
|
905 CRMFPKIArchiveOptions *srcOpt) |
|
906 { |
|
907 SECStatus rv; |
|
908 destOpt->archOption = srcOpt->archOption; |
|
909 switch (srcOpt->archOption) { |
|
910 case crmfEncryptedPrivateKey: |
|
911 rv = crmf_copy_encryptedkey(poolp, |
|
912 &srcOpt->option.encryptedKey, |
|
913 &destOpt->option.encryptedKey); |
|
914 break; |
|
915 case crmfKeyGenParameters: |
|
916 case crmfArchiveRemGenPrivKey: |
|
917 /* We've got a union, so having a pointer to one is just |
|
918 * like having a pointer to the other one. |
|
919 */ |
|
920 rv = SECITEM_CopyItem(poolp, |
|
921 &destOpt->option.keyGenParameters, |
|
922 &srcOpt->option.keyGenParameters); |
|
923 break; |
|
924 default: |
|
925 rv = SECFailure; |
|
926 } |
|
927 return rv; |
|
928 } |
|
929 |
|
930 static SECStatus |
|
931 crmf_check_and_adjust_archoption(CRMFControl *inControl) |
|
932 { |
|
933 CRMFPKIArchiveOptions *options; |
|
934 |
|
935 options = &inControl->value.archiveOptions; |
|
936 if (options->archOption == crmfNoArchiveOptions) { |
|
937 /* It hasn't been set, so figure it out from the |
|
938 * der. |
|
939 */ |
|
940 switch (inControl->derValue.data[0] & 0x0f) { |
|
941 case 0: |
|
942 options->archOption = crmfEncryptedPrivateKey; |
|
943 break; |
|
944 case 1: |
|
945 options->archOption = crmfKeyGenParameters; |
|
946 break; |
|
947 case 2: |
|
948 options->archOption = crmfArchiveRemGenPrivKey; |
|
949 break; |
|
950 default: |
|
951 /* We've got bad DER. Return an error. */ |
|
952 return SECFailure; |
|
953 } |
|
954 } |
|
955 return SECSuccess; |
|
956 } |
|
957 |
|
958 static const SEC_ASN1Template * |
|
959 crmf_get_pkiarchive_subtemplate(CRMFControl *inControl) |
|
960 { |
|
961 const SEC_ASN1Template *retTemplate; |
|
962 SECStatus rv; |
|
963 /* |
|
964 * We could be in the process of decoding, in which case the |
|
965 * archOption field will not be set. Let's check it and set |
|
966 * it accordingly. |
|
967 */ |
|
968 |
|
969 rv = crmf_check_and_adjust_archoption(inControl); |
|
970 if (rv != SECSuccess) { |
|
971 return NULL; |
|
972 } |
|
973 |
|
974 switch (inControl->value.archiveOptions.archOption) { |
|
975 case crmfEncryptedPrivateKey: |
|
976 retTemplate = CRMFEncryptedKeyWithEncryptedValueTemplate; |
|
977 inControl->value.archiveOptions.option.encryptedKey.encKeyChoice = |
|
978 crmfEncryptedValueChoice; |
|
979 break; |
|
980 default: |
|
981 retTemplate = NULL; |
|
982 } |
|
983 return retTemplate; |
|
984 } |
|
985 |
|
986 const SEC_ASN1Template* |
|
987 crmf_get_pkiarchiveoptions_subtemplate(CRMFControl *inControl) |
|
988 { |
|
989 const SEC_ASN1Template *retTemplate; |
|
990 |
|
991 switch (inControl->tag) { |
|
992 case SEC_OID_PKIX_REGCTRL_REGTOKEN: |
|
993 case SEC_OID_PKIX_REGCTRL_AUTHENTICATOR: |
|
994 retTemplate = SEC_ASN1_GET(SEC_UTF8StringTemplate); |
|
995 break; |
|
996 case SEC_OID_PKIX_REGCTRL_PKI_ARCH_OPTIONS: |
|
997 retTemplate = crmf_get_pkiarchive_subtemplate(inControl); |
|
998 break; |
|
999 case SEC_OID_PKIX_REGCTRL_PKIPUBINFO: |
|
1000 case SEC_OID_PKIX_REGCTRL_OLD_CERT_ID: |
|
1001 case SEC_OID_PKIX_REGCTRL_PROTOCOL_ENC_KEY: |
|
1002 /* We don't support these controls, so we fail for now.*/ |
|
1003 retTemplate = NULL; |
|
1004 break; |
|
1005 default: |
|
1006 retTemplate = NULL; |
|
1007 } |
|
1008 return retTemplate; |
|
1009 } |
|
1010 |
|
1011 static SECStatus |
|
1012 crmf_encode_pkiarchiveoptions(PLArenaPool *poolp, CRMFControl *inControl) |
|
1013 { |
|
1014 const SEC_ASN1Template *asn1Template; |
|
1015 |
|
1016 asn1Template = crmf_get_pkiarchiveoptions_subtemplate(inControl); |
|
1017 /* We've got a union, so passing a pointer to one element of the |
|
1018 * union, is the same as passing a pointer to any of the other |
|
1019 * members of the union. |
|
1020 */ |
|
1021 SEC_ASN1EncodeItem(poolp, &inControl->derValue, |
|
1022 &inControl->value.archiveOptions, asn1Template); |
|
1023 |
|
1024 if (inControl->derValue.data == NULL) { |
|
1025 goto loser; |
|
1026 } |
|
1027 return SECSuccess; |
|
1028 loser: |
|
1029 return SECFailure; |
|
1030 } |
|
1031 |
|
1032 SECStatus |
|
1033 CRMF_CertRequestSetPKIArchiveOptions(CRMFCertRequest *inCertReq, |
|
1034 CRMFPKIArchiveOptions *inOptions) |
|
1035 { |
|
1036 CRMFControl *newControl; |
|
1037 PLArenaPool *poolp; |
|
1038 SECStatus rv; |
|
1039 void *mark; |
|
1040 |
|
1041 PORT_Assert(inCertReq != NULL && inOptions != NULL); |
|
1042 if (inCertReq == NULL || inOptions == NULL) { |
|
1043 return SECFailure; |
|
1044 } |
|
1045 poolp = inCertReq->poolp; |
|
1046 mark = PORT_ArenaMark(poolp); |
|
1047 rv = crmf_add_new_control(inCertReq, |
|
1048 SEC_OID_PKIX_REGCTRL_PKI_ARCH_OPTIONS, |
|
1049 &newControl); |
|
1050 if (rv != SECSuccess) { |
|
1051 goto loser; |
|
1052 } |
|
1053 |
|
1054 rv = crmf_copy_pkiarchiveoptions(poolp, |
|
1055 &newControl->value.archiveOptions, |
|
1056 inOptions); |
|
1057 if (rv != SECSuccess) { |
|
1058 goto loser; |
|
1059 } |
|
1060 |
|
1061 rv = crmf_encode_pkiarchiveoptions(poolp, newControl); |
|
1062 if (rv != SECSuccess) { |
|
1063 goto loser; |
|
1064 } |
|
1065 PORT_ArenaUnmark(poolp, mark); |
|
1066 return SECSuccess; |
|
1067 loser: |
|
1068 PORT_ArenaRelease(poolp, mark); |
|
1069 return SECFailure; |
|
1070 } |
|
1071 |
|
1072 static SECStatus |
|
1073 crmf_destroy_control(CRMFControl *inControl, PRBool freeit) |
|
1074 { |
|
1075 PORT_Assert(inControl != NULL); |
|
1076 if (inControl != NULL) { |
|
1077 SECITEM_FreeItem(&inControl->derTag, PR_FALSE); |
|
1078 SECITEM_FreeItem(&inControl->derValue, PR_FALSE); |
|
1079 /* None of the other tags require special processing at |
|
1080 * the moment when freeing because they are not supported, |
|
1081 * but if/when they are, add the necessary routines here. |
|
1082 * If all controls are supported, then every member of the |
|
1083 * union inControl->value will have a case that deals with |
|
1084 * it in the following switch statement. |
|
1085 */ |
|
1086 switch (inControl->tag) { |
|
1087 case SEC_OID_PKIX_REGCTRL_PKI_ARCH_OPTIONS: |
|
1088 crmf_destroy_pkiarchiveoptions(&inControl->value.archiveOptions, |
|
1089 PR_FALSE); |
|
1090 break; |
|
1091 default: |
|
1092 /* Put this here to get rid of all those annoying warnings.*/ |
|
1093 break; |
|
1094 } |
|
1095 if (freeit) { |
|
1096 PORT_Free(inControl); |
|
1097 } |
|
1098 } |
|
1099 return SECSuccess; |
|
1100 } |
|
1101 |
|
1102 SECStatus |
|
1103 CRMF_DestroyControl(CRMFControl *inControl) |
|
1104 { |
|
1105 return crmf_destroy_control(inControl, PR_TRUE); |
|
1106 } |
|
1107 |
|
1108 static SECOidTag |
|
1109 crmf_controltype_to_tag(CRMFControlType inControlType) |
|
1110 { |
|
1111 SECOidTag retVal; |
|
1112 |
|
1113 switch(inControlType) { |
|
1114 case crmfRegTokenControl: |
|
1115 retVal = SEC_OID_PKIX_REGCTRL_REGTOKEN; |
|
1116 break; |
|
1117 case crmfAuthenticatorControl: |
|
1118 retVal = SEC_OID_PKIX_REGCTRL_AUTHENTICATOR; |
|
1119 break; |
|
1120 case crmfPKIPublicationInfoControl: |
|
1121 retVal = SEC_OID_PKIX_REGCTRL_PKIPUBINFO; |
|
1122 break; |
|
1123 case crmfPKIArchiveOptionsControl: |
|
1124 retVal = SEC_OID_PKIX_REGCTRL_PKI_ARCH_OPTIONS; |
|
1125 break; |
|
1126 case crmfOldCertIDControl: |
|
1127 retVal = SEC_OID_PKIX_REGCTRL_OLD_CERT_ID; |
|
1128 break; |
|
1129 case crmfProtocolEncrKeyControl: |
|
1130 retVal = SEC_OID_PKIX_REGCTRL_PROTOCOL_ENC_KEY; |
|
1131 break; |
|
1132 default: |
|
1133 retVal = SEC_OID_UNKNOWN; |
|
1134 break; |
|
1135 } |
|
1136 return retVal; |
|
1137 } |
|
1138 |
|
1139 PRBool |
|
1140 CRMF_CertRequestIsControlPresent(CRMFCertRequest *inCertReq, |
|
1141 CRMFControlType inControlType) |
|
1142 { |
|
1143 SECOidTag controlTag; |
|
1144 int i; |
|
1145 |
|
1146 PORT_Assert(inCertReq != NULL); |
|
1147 if (inCertReq == NULL || inCertReq->controls == NULL) { |
|
1148 return PR_FALSE; |
|
1149 } |
|
1150 controlTag = crmf_controltype_to_tag(inControlType); |
|
1151 for (i=0; inCertReq->controls[i] != NULL; i++) { |
|
1152 if (inCertReq->controls[i]->tag == controlTag) { |
|
1153 return PR_TRUE; |
|
1154 } |
|
1155 } |
|
1156 return PR_FALSE; |
|
1157 } |
|
1158 |