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 const SEC_ASN1Template CERT_AttributeTemplate
[] = {
47 0, NULL
, sizeof(CERTAttribute
) },
48 { SEC_ASN1_OBJECT_ID
, offsetof(CERTAttribute
, attrType
) },
49 { SEC_ASN1_SET_OF
, offsetof(CERTAttribute
, attrValue
),
54 const SEC_ASN1Template CERT_SetOfAttributeTemplate
[] = {
55 { SEC_ASN1_SET_OF
, 0, CERT_AttributeTemplate
},
58 const SEC_ASN1Template CERT_CertificateRequestTemplate
[] = {
60 0, NULL
, sizeof(CERTCertificateRequest
) },
62 offsetof(CERTCertificateRequest
,version
) },
64 offsetof(CERTCertificateRequest
,subject
),
67 offsetof(CERTCertificateRequest
,subjectPublicKeyInfo
),
68 CERT_SubjectPublicKeyInfoTemplate
},
69 { SEC_ASN1_CONSTRUCTED
| SEC_ASN1_CONTEXT_SPECIFIC
| 0,
70 offsetof(CERTCertificateRequest
,attributes
),
71 CERT_SetOfAttributeTemplate
},
75 SEC_ASN1_CHOOSER_IMPLEMENT(CERT_CertificateRequestTemplate
)
78 CERT_CreateCertificate(unsigned long serialNumber
,
80 CERTValidity
*validity
,
81 CERTCertificateRequest
*req
)
87 arena
= PORT_NewArena(DER_DEFAULT_CHUNKSIZE
);
93 c
= (CERTCertificate
*)PORT_ArenaZAlloc(arena
, sizeof(CERTCertificate
));
96 c
->referenceCount
= 1;
100 * Default is a plain version 1.
101 * If extensions are added, it will get changed as appropriate.
103 rv
= DER_SetUInteger(arena
, &c
->version
, SEC_CERTIFICATE_VERSION_1
);
106 rv
= DER_SetUInteger(arena
, &c
->serialNumber
, serialNumber
);
109 rv
= CERT_CopyName(arena
, &c
->issuer
, issuer
);
112 rv
= CERT_CopyValidity(arena
, &c
->validity
, validity
);
115 rv
= CERT_CopyName(arena
, &c
->subject
, &req
->subject
);
117 rv
= SECKEY_CopySubjectPublicKeyInfo(arena
, &c
->subjectPublicKeyInfo
,
118 &req
->subjectPublicKeyInfo
);
124 CERT_DestroyCertificate(c
);
128 /************************************************************************/
129 /* It's clear from the comments that the original author of this
130 * function expected the template for certificate requests to treat
131 * the attributes as a SET OF ANY. This function expected to be
132 * passed an array of SECItems each of which contained an already encoded
133 * Attribute. But the cert request template does not treat the
134 * Attributes as a SET OF ANY, and AFAIK never has. Instead the template
135 * encodes attributes as a SET OF xxxxxxx. That is, it expects to encode
136 * each of the Attributes, not have them pre-encoded. Consequently an
137 * array of SECItems containing encoded Attributes is of no value to this
138 * function. But we cannot change the signature of this public function.
139 * It must continue to take SECItems.
141 * I have recoded this function so that each SECItem contains an
142 * encoded cert extension. The encoded cert extensions form the list for the
143 * single attribute of the cert request. In this implementation there is at most
144 * one attribute and it is always of type SEC_OID_PKCS9_EXTENSION_REQUEST.
147 CERTCertificateRequest
*
148 CERT_CreateCertificateRequest(CERTName
*subject
,
149 CERTSubjectPublicKeyInfo
*spki
,
150 SECItem
**attributes
)
152 CERTCertificateRequest
*certreq
;
154 CERTAttribute
* attribute
;
155 SECOidData
* oidData
;
159 arena
= PORT_NewArena(DER_DEFAULT_CHUNKSIZE
);
160 if ( arena
== NULL
) {
164 certreq
= PORT_ArenaZNew(arena
, CERTCertificateRequest
);
166 PORT_FreeArena(arena
, PR_FALSE
);
169 /* below here it is safe to goto loser */
171 certreq
->arena
= arena
;
173 rv
= DER_SetUInteger(arena
, &certreq
->version
,
174 SEC_CERTIFICATE_REQUEST_VERSION
);
175 if (rv
!= SECSuccess
)
178 rv
= CERT_CopyName(arena
, &certreq
->subject
, subject
);
179 if (rv
!= SECSuccess
)
182 rv
= SECKEY_CopySubjectPublicKeyInfo(arena
,
183 &certreq
->subjectPublicKeyInfo
,
185 if (rv
!= SECSuccess
)
188 certreq
->attributes
= PORT_ArenaZNewArray(arena
, CERTAttribute
*, 2);
189 if(!certreq
->attributes
)
192 /* Copy over attribute information */
193 if (!attributes
|| !attributes
[0]) {
195 ** Invent empty attribute information. According to the
196 ** pkcs#10 spec, attributes has this ASN.1 type:
198 ** attributes [0] IMPLICIT Attributes
200 ** Which means, we should create a NULL terminated list
201 ** with the first entry being NULL;
203 certreq
->attributes
[0] = NULL
;
207 /* allocate space for attributes */
208 attribute
= PORT_ArenaZNew(arena
, CERTAttribute
);
212 oidData
= SECOID_FindOIDByTag( SEC_OID_PKCS9_EXTENSION_REQUEST
);
213 PORT_Assert(oidData
);
216 rv
= SECITEM_CopyItem(arena
, &attribute
->attrType
, &oidData
->oid
);
217 if (rv
!= SECSuccess
)
220 for (i
= 0; attributes
[i
] != NULL
; i
++)
222 attribute
->attrValue
= PORT_ArenaZNewArray(arena
, SECItem
*, i
+1);
223 if (!attribute
->attrValue
)
226 /* copy attributes */
227 for (i
= 0; attributes
[i
]; i
++) {
229 ** Attributes are a SetOf Attribute which implies
230 ** lexigraphical ordering. It is assumes that the
231 ** attributes are passed in sorted. If we need to
232 ** add functionality to sort them, there is an
233 ** example in the PKCS 7 code.
235 attribute
->attrValue
[i
] = SECITEM_ArenaDupItem(arena
, attributes
[i
]);
236 if(!attribute
->attrValue
[i
])
240 certreq
->attributes
[0] = attribute
;
245 CERT_DestroyCertificateRequest(certreq
);
250 CERT_DestroyCertificateRequest(CERTCertificateRequest
*req
)
252 if (req
&& req
->arena
) {
253 PORT_FreeArena(req
->arena
, PR_FALSE
);
259 setCRExt(void *o
, CERTCertExtension
**exts
)
261 ((CERTCertificateRequest
*)o
)->attributes
= (struct CERTAttributeStr
**)exts
;
265 ** Set up to start gathering cert extensions for a cert request.
266 ** The list is created as CertExtensions and converted to an
267 ** attribute list by CERT_FinishCRAttributes().
269 extern void *cert_StartExtensions(void *owner
, PRArenaPool
*ownerArena
,
270 void (*setExts
)(void *object
, CERTCertExtension
**exts
));
272 CERT_StartCertificateRequestAttributes(CERTCertificateRequest
*req
)
274 return (cert_StartExtensions ((void *)req
, req
->arena
, setCRExt
));
278 ** At entry req->attributes actually contains an list of cert extensions--
279 ** req-attributes is overloaded until the list is DER encoded (the first
280 ** ...EncodeItem() below).
281 ** We turn this into an attribute list by encapsulating it
282 ** in a PKCS 10 Attribute structure
285 CERT_FinishCertificateRequestAttributes(CERTCertificateRequest
*req
)
288 CERTAttribute
*attribute
;
290 if (!req
|| !req
->arena
) {
291 PORT_SetError(SEC_ERROR_INVALID_ARGS
);
294 if (req
->attributes
== NULL
|| req
->attributes
[0] == NULL
)
297 extlist
= SEC_ASN1EncodeItem(req
->arena
, NULL
, &req
->attributes
,
298 SEC_ASN1_GET(CERT_SequenceOfCertExtensionTemplate
));
302 oidrec
= SECOID_FindOIDByTag(SEC_OID_PKCS9_EXTENSION_REQUEST
);
306 /* now change the list of cert extensions into a list of attributes
308 req
->attributes
= PORT_ArenaZNewArray(req
->arena
, CERTAttribute
*, 2);
310 attribute
= PORT_ArenaZNew(req
->arena
, CERTAttribute
);
312 if (req
->attributes
== NULL
|| attribute
== NULL
||
313 SECITEM_CopyItem(req
->arena
, &attribute
->attrType
, &oidrec
->oid
) != 0) {
314 PORT_SetError(SEC_ERROR_NO_MEMORY
);
317 attribute
->attrValue
= PORT_ArenaZNewArray(req
->arena
, SECItem
*, 2);
319 if (attribute
->attrValue
== NULL
)
322 attribute
->attrValue
[0] = extlist
;
323 attribute
->attrValue
[1] = NULL
;
324 req
->attributes
[0] = attribute
;
325 req
->attributes
[1] = NULL
;
331 CERT_GetCertificateRequestExtensions(CERTCertificateRequest
*req
,
332 CERTCertExtension
***exts
)
334 if (req
== NULL
|| exts
== NULL
) {
335 PORT_SetError(SEC_ERROR_INVALID_ARGS
);
339 if (req
->attributes
== NULL
|| *req
->attributes
== NULL
)
342 if ((*req
->attributes
)->attrValue
== NULL
) {
343 PORT_SetError(SEC_ERROR_INVALID_ARGS
);
347 return(SEC_ASN1DecodeItem(req
->arena
, exts
,
348 SEC_ASN1_GET(CERT_SequenceOfCertExtensionTemplate
),
349 (*req
->attributes
)->attrValue
[0]));