|
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 "keyhi.h" |
|
9 #include "secder.h" |
|
10 |
|
11 |
|
12 CRMFPOPChoice |
|
13 CRMF_CertReqMsgGetPOPType(CRMFCertReqMsg *inCertReqMsg) |
|
14 { |
|
15 PORT_Assert(inCertReqMsg != NULL); |
|
16 if (inCertReqMsg != NULL && inCertReqMsg->pop != NULL) { |
|
17 return inCertReqMsg->pop->popUsed; |
|
18 } |
|
19 return crmfNoPOPChoice; |
|
20 } |
|
21 |
|
22 static SECStatus |
|
23 crmf_destroy_validity(CRMFOptionalValidity *inValidity, PRBool freeit) |
|
24 { |
|
25 if (inValidity != NULL){ |
|
26 if (inValidity->notBefore.data != NULL) { |
|
27 PORT_Free(inValidity->notBefore.data); |
|
28 } |
|
29 if (inValidity->notAfter.data != NULL) { |
|
30 PORT_Free(inValidity->notAfter.data); |
|
31 } |
|
32 if (freeit) { |
|
33 PORT_Free(inValidity); |
|
34 } |
|
35 } |
|
36 return SECSuccess; |
|
37 } |
|
38 |
|
39 static SECStatus |
|
40 crmf_copy_cert_request_validity(PLArenaPool *poolp, |
|
41 CRMFOptionalValidity **destValidity, |
|
42 CRMFOptionalValidity *srcValidity) |
|
43 { |
|
44 CRMFOptionalValidity *myValidity = NULL; |
|
45 SECStatus rv; |
|
46 |
|
47 *destValidity = myValidity = (poolp == NULL) ? |
|
48 PORT_ZNew(CRMFOptionalValidity) : |
|
49 PORT_ArenaZNew(poolp, CRMFOptionalValidity); |
|
50 if (myValidity == NULL) { |
|
51 goto loser; |
|
52 } |
|
53 if (srcValidity->notBefore.data != NULL) { |
|
54 rv = SECITEM_CopyItem(poolp, &myValidity->notBefore, |
|
55 &srcValidity->notBefore); |
|
56 if (rv != SECSuccess) { |
|
57 goto loser; |
|
58 } |
|
59 } |
|
60 if (srcValidity->notAfter.data != NULL) { |
|
61 rv = SECITEM_CopyItem(poolp, &myValidity->notAfter, |
|
62 &srcValidity->notAfter); |
|
63 if (rv != SECSuccess) { |
|
64 goto loser; |
|
65 } |
|
66 } |
|
67 return SECSuccess; |
|
68 loser: |
|
69 if (myValidity != NULL && poolp == NULL) { |
|
70 crmf_destroy_validity(myValidity, PR_TRUE); |
|
71 } |
|
72 return SECFailure; |
|
73 } |
|
74 |
|
75 static SECStatus |
|
76 crmf_copy_extensions(PLArenaPool *poolp, |
|
77 CRMFCertTemplate *destTemplate, |
|
78 CRMFCertExtension **srcExt) |
|
79 { |
|
80 int numExt = 0, i; |
|
81 CRMFCertExtension **myExtArray = NULL; |
|
82 |
|
83 while (srcExt[numExt] != NULL) { |
|
84 numExt++; |
|
85 } |
|
86 if (numExt == 0) { |
|
87 /*No extensions to copy.*/ |
|
88 destTemplate->extensions = NULL; |
|
89 destTemplate->numExtensions = 0; |
|
90 return SECSuccess; |
|
91 } |
|
92 destTemplate->extensions = myExtArray = |
|
93 PORT_NewArray(CRMFCertExtension*, numExt+1); |
|
94 if (myExtArray == NULL) { |
|
95 goto loser; |
|
96 } |
|
97 |
|
98 for (i=0; i<numExt; i++) { |
|
99 myExtArray[i] = crmf_copy_cert_extension(poolp, srcExt[i]); |
|
100 if (myExtArray[i] == NULL) { |
|
101 goto loser; |
|
102 } |
|
103 } |
|
104 destTemplate->numExtensions = numExt; |
|
105 myExtArray[numExt] = NULL; |
|
106 return SECSuccess; |
|
107 loser: |
|
108 if (myExtArray != NULL) { |
|
109 if (poolp == NULL) { |
|
110 for (i=0; myExtArray[i] != NULL; i++) { |
|
111 CRMF_DestroyCertExtension(myExtArray[i]); |
|
112 } |
|
113 } |
|
114 PORT_Free(myExtArray); |
|
115 } |
|
116 destTemplate->extensions = NULL; |
|
117 destTemplate->numExtensions = 0; |
|
118 return SECFailure; |
|
119 } |
|
120 |
|
121 static SECStatus |
|
122 crmf_copy_cert_request_template(PLArenaPool *poolp, |
|
123 CRMFCertTemplate *destTemplate, |
|
124 CRMFCertTemplate *srcTemplate) |
|
125 { |
|
126 SECStatus rv; |
|
127 |
|
128 if (srcTemplate->version.data != NULL) { |
|
129 rv = SECITEM_CopyItem(poolp, &destTemplate->version, |
|
130 &srcTemplate->version); |
|
131 if (rv != SECSuccess) { |
|
132 goto loser; |
|
133 } |
|
134 } |
|
135 if (srcTemplate->serialNumber.data != NULL) { |
|
136 rv = SECITEM_CopyItem(poolp, &destTemplate->serialNumber, |
|
137 &srcTemplate->serialNumber); |
|
138 if (rv != SECSuccess) { |
|
139 goto loser; |
|
140 } |
|
141 } |
|
142 if (srcTemplate->signingAlg != NULL) { |
|
143 rv = crmf_template_copy_secalg(poolp, &destTemplate->signingAlg, |
|
144 srcTemplate->signingAlg); |
|
145 if (rv != SECSuccess) { |
|
146 goto loser; |
|
147 } |
|
148 } |
|
149 if (srcTemplate->issuer != NULL) { |
|
150 rv = crmf_copy_cert_name(poolp, &destTemplate->issuer, |
|
151 srcTemplate->issuer); |
|
152 if (rv != SECSuccess) { |
|
153 goto loser; |
|
154 } |
|
155 } |
|
156 if (srcTemplate->validity != NULL) { |
|
157 rv = crmf_copy_cert_request_validity(poolp, &destTemplate->validity, |
|
158 srcTemplate->validity); |
|
159 if (rv != SECSuccess) { |
|
160 goto loser; |
|
161 } |
|
162 } |
|
163 if (srcTemplate->subject != NULL) { |
|
164 rv = crmf_copy_cert_name(poolp, &destTemplate->subject, |
|
165 srcTemplate->subject); |
|
166 if (rv != SECSuccess) { |
|
167 goto loser; |
|
168 } |
|
169 } |
|
170 if (srcTemplate->publicKey != NULL) { |
|
171 rv = crmf_template_add_public_key(poolp, &destTemplate->publicKey, |
|
172 srcTemplate->publicKey); |
|
173 if (rv != SECSuccess) { |
|
174 goto loser; |
|
175 } |
|
176 } |
|
177 if (srcTemplate->issuerUID.data != NULL) { |
|
178 rv = crmf_make_bitstring_copy(poolp, &destTemplate->issuerUID, |
|
179 &srcTemplate->issuerUID); |
|
180 if (rv != SECSuccess) { |
|
181 goto loser; |
|
182 } |
|
183 } |
|
184 if (srcTemplate->subjectUID.data != NULL) { |
|
185 rv = crmf_make_bitstring_copy(poolp, &destTemplate->subjectUID, |
|
186 &srcTemplate->subjectUID); |
|
187 if (rv != SECSuccess) { |
|
188 goto loser; |
|
189 } |
|
190 } |
|
191 if (srcTemplate->extensions != NULL) { |
|
192 rv = crmf_copy_extensions(poolp, destTemplate, |
|
193 srcTemplate->extensions); |
|
194 if (rv != SECSuccess) { |
|
195 goto loser; |
|
196 } |
|
197 } |
|
198 return SECSuccess; |
|
199 loser: |
|
200 return SECFailure; |
|
201 } |
|
202 |
|
203 static CRMFControl* |
|
204 crmf_copy_control(PLArenaPool *poolp, CRMFControl *srcControl) |
|
205 { |
|
206 CRMFControl *newControl; |
|
207 SECStatus rv; |
|
208 |
|
209 newControl = (poolp == NULL) ? PORT_ZNew(CRMFControl) : |
|
210 PORT_ArenaZNew(poolp, CRMFControl); |
|
211 if (newControl == NULL) { |
|
212 goto loser; |
|
213 } |
|
214 newControl->tag = srcControl->tag; |
|
215 rv = SECITEM_CopyItem(poolp, &newControl->derTag, &srcControl->derTag); |
|
216 if (rv != SECSuccess) { |
|
217 goto loser; |
|
218 } |
|
219 rv = SECITEM_CopyItem(poolp, &newControl->derValue, &srcControl->derValue); |
|
220 if (rv != SECSuccess) { |
|
221 goto loser; |
|
222 } |
|
223 /* We only handle PKIArchiveOptions Control right now. But if in |
|
224 * the future, more controls that are part of the union are added, |
|
225 * then they need to be handled here as well. |
|
226 */ |
|
227 switch (newControl->tag) { |
|
228 case SEC_OID_PKIX_REGCTRL_PKI_ARCH_OPTIONS: |
|
229 rv = crmf_copy_pkiarchiveoptions(poolp, |
|
230 &newControl->value.archiveOptions, |
|
231 &srcControl->value.archiveOptions); |
|
232 break; |
|
233 default: |
|
234 rv = SECSuccess; |
|
235 } |
|
236 if (rv != SECSuccess) { |
|
237 goto loser; |
|
238 } |
|
239 return newControl; |
|
240 |
|
241 loser: |
|
242 if (poolp == NULL && newControl != NULL) { |
|
243 CRMF_DestroyControl(newControl); |
|
244 } |
|
245 return NULL; |
|
246 } |
|
247 |
|
248 static SECStatus |
|
249 crmf_copy_cert_request_controls(PLArenaPool *poolp, |
|
250 CRMFCertRequest *destReq, |
|
251 CRMFCertRequest *srcReq) |
|
252 { |
|
253 int numControls, i; |
|
254 CRMFControl **myControls = NULL; |
|
255 |
|
256 numControls = CRMF_CertRequestGetNumControls(srcReq); |
|
257 if (numControls == 0) { |
|
258 /* No Controls To Copy*/ |
|
259 return SECSuccess; |
|
260 } |
|
261 myControls = destReq->controls = PORT_NewArray(CRMFControl*, |
|
262 numControls+1); |
|
263 if (myControls == NULL) { |
|
264 goto loser; |
|
265 } |
|
266 for (i=0; i<numControls; i++) { |
|
267 myControls[i] = crmf_copy_control(poolp, srcReq->controls[i]); |
|
268 if (myControls[i] == NULL) { |
|
269 goto loser; |
|
270 } |
|
271 } |
|
272 myControls[numControls] = NULL; |
|
273 return SECSuccess; |
|
274 loser: |
|
275 if (myControls != NULL) { |
|
276 if (poolp == NULL) { |
|
277 for (i=0; myControls[i] != NULL; i++) { |
|
278 CRMF_DestroyControl(myControls[i]); |
|
279 } |
|
280 } |
|
281 PORT_Free(myControls); |
|
282 } |
|
283 return SECFailure; |
|
284 } |
|
285 |
|
286 |
|
287 CRMFCertRequest* |
|
288 crmf_copy_cert_request(PLArenaPool *poolp, CRMFCertRequest *srcReq) |
|
289 { |
|
290 CRMFCertRequest *newReq = NULL; |
|
291 SECStatus rv; |
|
292 |
|
293 if (srcReq == NULL) { |
|
294 return NULL; |
|
295 } |
|
296 newReq = (poolp == NULL) ? PORT_ZNew(CRMFCertRequest) : |
|
297 PORT_ArenaZNew(poolp, CRMFCertRequest); |
|
298 if (newReq == NULL) { |
|
299 goto loser; |
|
300 } |
|
301 rv = SECITEM_CopyItem(poolp, &newReq->certReqId, &srcReq->certReqId); |
|
302 if (rv != SECSuccess) { |
|
303 goto loser; |
|
304 } |
|
305 rv = crmf_copy_cert_request_template(poolp, &newReq->certTemplate, |
|
306 &srcReq->certTemplate); |
|
307 if (rv != SECSuccess) { |
|
308 goto loser; |
|
309 } |
|
310 rv = crmf_copy_cert_request_controls(poolp, newReq, srcReq); |
|
311 if (rv != SECSuccess) { |
|
312 goto loser; |
|
313 } |
|
314 return newReq; |
|
315 loser: |
|
316 if (newReq != NULL && poolp == NULL) { |
|
317 CRMF_DestroyCertRequest(newReq); |
|
318 PORT_Free(newReq); |
|
319 } |
|
320 return NULL; |
|
321 } |
|
322 |
|
323 SECStatus |
|
324 CRMF_DestroyGetValidity(CRMFGetValidity *inValidity) |
|
325 { |
|
326 PORT_Assert(inValidity != NULL); |
|
327 if (inValidity != NULL) { |
|
328 if (inValidity->notAfter) { |
|
329 PORT_Free(inValidity->notAfter); |
|
330 inValidity->notAfter = NULL; |
|
331 } |
|
332 if (inValidity->notBefore) { |
|
333 PORT_Free(inValidity->notBefore); |
|
334 inValidity->notBefore = NULL; |
|
335 } |
|
336 } |
|
337 return SECSuccess; |
|
338 } |
|
339 |
|
340 SECStatus |
|
341 crmf_make_bitstring_copy(PLArenaPool *arena, SECItem *dest, SECItem *src) |
|
342 { |
|
343 int origLenBits; |
|
344 int bytesToCopy; |
|
345 SECStatus rv; |
|
346 |
|
347 origLenBits = src->len; |
|
348 bytesToCopy = CRMF_BITS_TO_BYTES(origLenBits); |
|
349 src->len = bytesToCopy; |
|
350 rv = SECITEM_CopyItem(arena, dest, src); |
|
351 src->len = origLenBits; |
|
352 if (rv != SECSuccess) { |
|
353 return rv; |
|
354 } |
|
355 dest->len = origLenBits; |
|
356 return SECSuccess; |
|
357 } |
|
358 |
|
359 int |
|
360 CRMF_CertRequestGetNumberOfExtensions(CRMFCertRequest *inCertReq) |
|
361 { |
|
362 CRMFCertTemplate *certTemplate; |
|
363 int count = 0; |
|
364 |
|
365 certTemplate = &inCertReq->certTemplate; |
|
366 if (certTemplate->extensions) { |
|
367 while (certTemplate->extensions[count] != NULL) |
|
368 count++; |
|
369 } |
|
370 return count; |
|
371 } |
|
372 |
|
373 SECOidTag |
|
374 CRMF_CertExtensionGetOidTag(CRMFCertExtension *inExtension) |
|
375 { |
|
376 PORT_Assert(inExtension != NULL); |
|
377 if (inExtension == NULL) { |
|
378 return SEC_OID_UNKNOWN; |
|
379 } |
|
380 return SECOID_FindOIDTag(&inExtension->id); |
|
381 } |
|
382 |
|
383 PRBool |
|
384 CRMF_CertExtensionGetIsCritical(CRMFCertExtension *inExt) |
|
385 { |
|
386 PORT_Assert(inExt != NULL); |
|
387 if (inExt == NULL) { |
|
388 return PR_FALSE; |
|
389 } |
|
390 return inExt->critical.data != NULL; |
|
391 } |
|
392 |
|
393 SECItem* |
|
394 CRMF_CertExtensionGetValue(CRMFCertExtension *inExtension) |
|
395 { |
|
396 PORT_Assert(inExtension != NULL); |
|
397 if (inExtension == NULL) { |
|
398 return NULL; |
|
399 } |
|
400 |
|
401 return SECITEM_DupItem(&inExtension->value); |
|
402 } |
|
403 |
|
404 |
|
405 SECStatus |
|
406 CRMF_DestroyPOPOSigningKey(CRMFPOPOSigningKey *inKey) |
|
407 { |
|
408 PORT_Assert(inKey != NULL); |
|
409 if (inKey != NULL) { |
|
410 if (inKey->derInput.data != NULL) { |
|
411 SECITEM_FreeItem(&inKey->derInput, PR_FALSE); |
|
412 } |
|
413 if (inKey->algorithmIdentifier != NULL) { |
|
414 SECOID_DestroyAlgorithmID(inKey->algorithmIdentifier, PR_TRUE); |
|
415 } |
|
416 if (inKey->signature.data != NULL) { |
|
417 SECITEM_FreeItem(&inKey->signature, PR_FALSE); |
|
418 } |
|
419 PORT_Free(inKey); |
|
420 } |
|
421 return SECSuccess; |
|
422 } |
|
423 |
|
424 SECStatus |
|
425 CRMF_DestroyPOPOPrivKey(CRMFPOPOPrivKey *inPrivKey) |
|
426 { |
|
427 PORT_Assert(inPrivKey != NULL); |
|
428 if (inPrivKey != NULL) { |
|
429 SECITEM_FreeItem(&inPrivKey->message.thisMessage, PR_FALSE); |
|
430 PORT_Free(inPrivKey); |
|
431 } |
|
432 return SECSuccess; |
|
433 } |
|
434 |
|
435 int |
|
436 CRMF_CertRequestGetNumControls(CRMFCertRequest *inCertReq) |
|
437 { |
|
438 int count = 0; |
|
439 |
|
440 PORT_Assert(inCertReq != NULL); |
|
441 if (inCertReq == NULL) { |
|
442 return 0; |
|
443 } |
|
444 if (inCertReq->controls) { |
|
445 while (inCertReq->controls[count] != NULL) |
|
446 count++; |
|
447 } |
|
448 return count; |
|
449 } |
|
450 |