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