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