1 /* ***** BEGIN LICENSE BLOCK *****
2 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
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
6 * the License. You may obtain a copy of the License at
7 * http://www.mozilla.org/MPL/
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
11 * for the specific language governing rights and limitations under the
14 * The Original Code is the Netscape security libraries.
16 * The Initial Developer of the Original Code is
17 * Netscape Communications Corporation.
18 * Portions created by the Initial Developer are Copyright (C) 1994-2000
19 * the Initial Developer. All Rights Reserved.
23 * Alternatively, the contents of this file may be used under the terms of
24 * either the GNU General Public License Version 2 or later (the "GPL"), or
25 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
26 * in which case the provisions of the GPL or the LGPL are applicable instead
27 * of those above. If you wish to allow use of your version of this file only
28 * under the terms of either the GPL or the LGPL, and not to allow others to
29 * use your version of this file under the terms of the MPL, indicate your
30 * decision by deleting the provisions above and replace them with the notice
31 * and other provisions required by the GPL or the LGPL. If you do not delete
32 * the provisions above, a recipient may use your version of this file under
33 * the terms of any one of the MPL, the GPL or the LGPL.
35 * ***** END LICENSE BLOCK ***** */
45 SEC_ASN1_MKSUB(SEC_AnyTemplate
)
47 const SEC_ASN1Template CERT_AttributeTemplate
[] = {
49 0, NULL
, sizeof(CERTAttribute
) },
50 { SEC_ASN1_OBJECT_ID
, offsetof(CERTAttribute
, attrType
) },
51 { SEC_ASN1_SET_OF
| SEC_ASN1_XTRN
, offsetof(CERTAttribute
, attrValue
),
52 SEC_ASN1_SUB(SEC_AnyTemplate
) },
56 const SEC_ASN1Template CERT_SetOfAttributeTemplate
[] = {
57 { SEC_ASN1_SET_OF
, 0, CERT_AttributeTemplate
},
60 const SEC_ASN1Template CERT_CertificateRequestTemplate
[] = {
62 0, NULL
, sizeof(CERTCertificateRequest
) },
64 offsetof(CERTCertificateRequest
,version
) },
66 offsetof(CERTCertificateRequest
,subject
),
69 offsetof(CERTCertificateRequest
,subjectPublicKeyInfo
),
70 CERT_SubjectPublicKeyInfoTemplate
},
71 { SEC_ASN1_CONSTRUCTED
| SEC_ASN1_CONTEXT_SPECIFIC
| 0,
72 offsetof(CERTCertificateRequest
,attributes
),
73 CERT_SetOfAttributeTemplate
},
77 SEC_ASN1_CHOOSER_IMPLEMENT(CERT_CertificateRequestTemplate
)
80 CERT_CreateCertificate(unsigned long serialNumber
,
82 CERTValidity
*validity
,
83 CERTCertificateRequest
*req
)
89 arena
= PORT_NewArena(DER_DEFAULT_CHUNKSIZE
);
95 c
= (CERTCertificate
*)PORT_ArenaZAlloc(arena
, sizeof(CERTCertificate
));
98 c
->referenceCount
= 1;
102 * Default is a plain version 1.
103 * If extensions are added, it will get changed as appropriate.
105 rv
= DER_SetUInteger(arena
, &c
->version
, SEC_CERTIFICATE_VERSION_1
);
108 rv
= DER_SetUInteger(arena
, &c
->serialNumber
, serialNumber
);
111 rv
= CERT_CopyName(arena
, &c
->issuer
, issuer
);
114 rv
= CERT_CopyValidity(arena
, &c
->validity
, validity
);
117 rv
= CERT_CopyName(arena
, &c
->subject
, &req
->subject
);
119 rv
= SECKEY_CopySubjectPublicKeyInfo(arena
, &c
->subjectPublicKeyInfo
,
120 &req
->subjectPublicKeyInfo
);
126 CERT_DestroyCertificate(c
);
130 /************************************************************************/
131 /* It's clear from the comments that the original author of this
132 * function expected the template for certificate requests to treat
133 * the attributes as a SET OF ANY. This function expected to be
134 * passed an array of SECItems each of which contained an already encoded
135 * Attribute. But the cert request template does not treat the
136 * Attributes as a SET OF ANY, and AFAIK never has. Instead the template
137 * encodes attributes as a SET OF xxxxxxx. That is, it expects to encode
138 * each of the Attributes, not have them pre-encoded. Consequently an
139 * array of SECItems containing encoded Attributes is of no value to this
140 * function. But we cannot change the signature of this public function.
141 * It must continue to take SECItems.
143 * I have recoded this function so that each SECItem contains an
144 * encoded cert extension. The encoded cert extensions form the list for the
145 * single attribute of the cert request. In this implementation there is at most
146 * one attribute and it is always of type SEC_OID_PKCS9_EXTENSION_REQUEST.
149 CERTCertificateRequest
*
150 CERT_CreateCertificateRequest(CERTName
*subject
,
151 CERTSubjectPublicKeyInfo
*spki
,
152 SECItem
**attributes
)
154 CERTCertificateRequest
*certreq
;
156 CERTAttribute
* attribute
;
157 SECOidData
* oidData
;
161 arena
= PORT_NewArena(DER_DEFAULT_CHUNKSIZE
);
162 if ( arena
== NULL
) {
166 certreq
= PORT_ArenaZNew(arena
, CERTCertificateRequest
);
168 PORT_FreeArena(arena
, PR_FALSE
);
171 /* below here it is safe to goto loser */
173 certreq
->arena
= arena
;
175 rv
= DER_SetUInteger(arena
, &certreq
->version
,
176 SEC_CERTIFICATE_REQUEST_VERSION
);
177 if (rv
!= SECSuccess
)
180 rv
= CERT_CopyName(arena
, &certreq
->subject
, subject
);
181 if (rv
!= SECSuccess
)
184 rv
= SECKEY_CopySubjectPublicKeyInfo(arena
,
185 &certreq
->subjectPublicKeyInfo
,
187 if (rv
!= SECSuccess
)
190 certreq
->attributes
= PORT_ArenaZNewArray(arena
, CERTAttribute
*, 2);
191 if(!certreq
->attributes
)
194 /* Copy over attribute information */
195 if (!attributes
|| !attributes
[0]) {
197 ** Invent empty attribute information. According to the
198 ** pkcs#10 spec, attributes has this ASN.1 type:
200 ** attributes [0] IMPLICIT Attributes
202 ** Which means, we should create a NULL terminated list
203 ** with the first entry being NULL;
205 certreq
->attributes
[0] = NULL
;
209 /* allocate space for attributes */
210 attribute
= PORT_ArenaZNew(arena
, CERTAttribute
);
214 oidData
= SECOID_FindOIDByTag( SEC_OID_PKCS9_EXTENSION_REQUEST
);
215 PORT_Assert(oidData
);
218 rv
= SECITEM_CopyItem(arena
, &attribute
->attrType
, &oidData
->oid
);
219 if (rv
!= SECSuccess
)
222 for (i
= 0; attributes
[i
] != NULL
; i
++)
224 attribute
->attrValue
= PORT_ArenaZNewArray(arena
, SECItem
*, i
+1);
225 if (!attribute
->attrValue
)
228 /* copy attributes */
229 for (i
= 0; attributes
[i
]; i
++) {
231 ** Attributes are a SetOf Attribute which implies
232 ** lexigraphical ordering. It is assumes that the
233 ** attributes are passed in sorted. If we need to
234 ** add functionality to sort them, there is an
235 ** example in the PKCS 7 code.
237 attribute
->attrValue
[i
] = SECITEM_ArenaDupItem(arena
, attributes
[i
]);
238 if(!attribute
->attrValue
[i
])
242 certreq
->attributes
[0] = attribute
;
247 CERT_DestroyCertificateRequest(certreq
);
252 CERT_DestroyCertificateRequest(CERTCertificateRequest
*req
)
254 if (req
&& req
->arena
) {
255 PORT_FreeArena(req
->arena
, PR_FALSE
);
261 setCRExt(void *o
, CERTCertExtension
**exts
)
263 ((CERTCertificateRequest
*)o
)->attributes
= (struct CERTAttributeStr
**)exts
;
267 ** Set up to start gathering cert extensions for a cert request.
268 ** The list is created as CertExtensions and converted to an
269 ** attribute list by CERT_FinishCRAttributes().
271 extern void *cert_StartExtensions(void *owner
, PRArenaPool
*ownerArena
,
272 void (*setExts
)(void *object
, CERTCertExtension
**exts
));
274 CERT_StartCertificateRequestAttributes(CERTCertificateRequest
*req
)
276 return (cert_StartExtensions ((void *)req
, req
->arena
, setCRExt
));
280 ** At entry req->attributes actually contains an list of cert extensions--
281 ** req-attributes is overloaded until the list is DER encoded (the first
282 ** ...EncodeItem() below).
283 ** We turn this into an attribute list by encapsulating it
284 ** in a PKCS 10 Attribute structure
287 CERT_FinishCertificateRequestAttributes(CERTCertificateRequest
*req
)
290 CERTAttribute
*attribute
;
292 if (!req
|| !req
->arena
) {
293 PORT_SetError(SEC_ERROR_INVALID_ARGS
);
296 if (req
->attributes
== NULL
|| req
->attributes
[0] == NULL
)
299 extlist
= SEC_ASN1EncodeItem(req
->arena
, NULL
, &req
->attributes
,
300 SEC_ASN1_GET(CERT_SequenceOfCertExtensionTemplate
));
304 oidrec
= SECOID_FindOIDByTag(SEC_OID_PKCS9_EXTENSION_REQUEST
);
308 /* now change the list of cert extensions into a list of attributes
310 req
->attributes
= PORT_ArenaZNewArray(req
->arena
, CERTAttribute
*, 2);
312 attribute
= PORT_ArenaZNew(req
->arena
, CERTAttribute
);
314 if (req
->attributes
== NULL
|| attribute
== NULL
||
315 SECITEM_CopyItem(req
->arena
, &attribute
->attrType
, &oidrec
->oid
) != 0) {
316 PORT_SetError(SEC_ERROR_NO_MEMORY
);
319 attribute
->attrValue
= PORT_ArenaZNewArray(req
->arena
, SECItem
*, 2);
321 if (attribute
->attrValue
== NULL
)
324 attribute
->attrValue
[0] = extlist
;
325 attribute
->attrValue
[1] = NULL
;
326 req
->attributes
[0] = attribute
;
327 req
->attributes
[1] = NULL
;
333 CERT_GetCertificateRequestExtensions(CERTCertificateRequest
*req
,
334 CERTCertExtension
***exts
)
336 if (req
== NULL
|| exts
== NULL
) {
337 PORT_SetError(SEC_ERROR_INVALID_ARGS
);
341 if (req
->attributes
== NULL
|| *req
->attributes
== NULL
)
344 if ((*req
->attributes
)->attrValue
== NULL
) {
345 PORT_SetError(SEC_ERROR_INVALID_ARGS
);
349 return(SEC_ASN1DecodeItem(req
->arena
, exts
,
350 SEC_ASN1_GET(CERT_SequenceOfCertExtensionTemplate
),
351 (*req
->attributes
)->attrValue
[0]));