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 ***** */
46 SEC_ASN1_MKSUB(SEC_AnyTemplate
)
49 SEC_ReadPKCS7Certs(SECItem
*pkcs7Item
, CERTImportCertificateFunc f
, void *arg
)
51 SEC_PKCS7ContentInfo
*contentInfo
= NULL
;
56 contentInfo
= SEC_PKCS7DecodeItem(pkcs7Item
, NULL
, NULL
, NULL
, NULL
, NULL
,
58 if ( contentInfo
== NULL
) {
62 if ( SEC_PKCS7ContentType (contentInfo
) != SEC_OID_PKCS7_SIGNED_DATA
) {
66 certs
= contentInfo
->content
.signedData
->rawCerts
;
74 rv
= (* f
)(arg
, contentInfo
->content
.signedData
->rawCerts
, count
);
85 SEC_PKCS7DestroyContentInfo(contentInfo
);
91 const SEC_ASN1Template SEC_CertSequenceTemplate
[] = {
92 { SEC_ASN1_SEQUENCE_OF
| SEC_ASN1_XTRN
, 0, SEC_ASN1_SUB(SEC_AnyTemplate
) }
96 SEC_ReadCertSequence(SECItem
*certsItem
, CERTImportCertificateFunc f
, void *arg
)
101 SECItem
**rawCerts
= NULL
;
103 SEC_PKCS7ContentInfo
*contentInfo
= NULL
;
105 arena
= PORT_NewArena(DER_DEFAULT_CHUNKSIZE
);
110 contentInfo
= SEC_PKCS7DecodeItem(certsItem
, NULL
, NULL
, NULL
, NULL
, NULL
,
112 if ( contentInfo
== NULL
) {
116 if ( SEC_PKCS7ContentType (contentInfo
) != SEC_OID_NS_TYPE_CERT_SEQUENCE
) {
121 rv
= SEC_QuickDERDecodeItem(arena
, &rawCerts
, SEC_CertSequenceTemplate
,
122 contentInfo
->content
.data
);
124 if (rv
!= SECSuccess
) {
136 rv
= (* f
)(arg
, rawCerts
, count
);
147 SEC_PKCS7DestroyContentInfo(contentInfo
);
151 PORT_FreeArena(arena
, PR_FALSE
);
158 CERT_ConvertAndDecodeCertificate(char *certstr
)
160 CERTCertificate
*cert
;
164 rv
= ATOB_ConvertAsciiToItem(&der
, certstr
);
165 if (rv
!= SECSuccess
)
168 cert
= CERT_NewTempCertificate(CERT_GetDefaultCertDB(),
169 &der
, NULL
, PR_FALSE
, PR_TRUE
);
175 static const char NS_CERT_HEADER
[] = "-----BEGIN CERTIFICATE-----";
176 static const char NS_CERT_TRAILER
[] = "-----END CERTIFICATE-----";
177 #define NS_CERT_HEADER_LEN ((sizeof NS_CERT_HEADER) - 1)
178 #define NS_CERT_TRAILER_LEN ((sizeof NS_CERT_TRAILER) - 1)
180 static const char CERTIFICATE_TYPE_STRING
[] = "certificate";
181 #define CERTIFICATE_TYPE_LEN (sizeof(CERTIFICATE_TYPE_STRING)-1)
184 * read an old style ascii or binary certificate chain
187 CERT_DecodeCertPackage(char *certbuf
,
189 CERTImportCertificateFunc f
,
193 unsigned char *bincert
= NULL
;
194 char * ascCert
= NULL
;
197 if ( certbuf
== NULL
) {
201 cp
= (unsigned char *)certbuf
;
203 /* is a DER encoded certificate of some type? */
204 if ( ( *cp
& 0x1f ) == SEC_ASN1_SEQUENCE
) {
206 SECItem
*pcertitem
= &certitem
;
207 int seqLen
, seqLenLen
;
212 /* Multibyte length */
213 seqLenLen
= cp
[0] & 0x7f;
217 seqLen
= ((unsigned long)cp
[1]<<24) |
218 ((unsigned long)cp
[2]<<16) | (cp
[3]<<8) | cp
[4];
221 seqLen
= ((unsigned long)cp
[1]<<16) | (cp
[2]<<8) | cp
[3];
224 seqLen
= (cp
[1]<<8) | cp
[2];
230 /* indefinite length */
233 cp
+= ( seqLenLen
+ 1 );
241 /* check entire length if definite length */
242 if ( seqLen
|| seqLenLen
) {
243 if ( certlen
!= ( seqLen
+ seqLenLen
+ 2 ) ) {
244 if (certlen
> ( seqLen
+ seqLenLen
+ 2 ))
245 PORT_SetError(SEC_ERROR_EXTRA_INPUT
);
247 PORT_SetError(SEC_ERROR_INPUT_LEN
);
252 /* check the type string */
253 /* netscape wrapped DER cert */
254 if ( ( cp
[0] == SEC_ASN1_OCTET_STRING
) &&
255 ( cp
[1] == CERTIFICATE_TYPE_LEN
) &&
256 ( PORT_Strcmp((char *)&cp
[2], CERTIFICATE_TYPE_STRING
) ) ) {
258 cp
+= ( CERTIFICATE_TYPE_LEN
+ 2 );
260 /* it had better be a certificate by now!! */
262 certitem
.len
= certlen
- ( cp
- (unsigned char *)certbuf
);
264 rv
= (* f
)(arg
, &pcertitem
, 1);
267 } else if ( cp
[0] == SEC_ASN1_OBJECT_ID
) {
270 /* XXX - assume DER encoding of OID len!! */
272 oiditem
.data
= (unsigned char *)&cp
[2];
273 oiddata
= SECOID_FindOID(&oiditem
);
274 if ( oiddata
== NULL
) {
278 certitem
.data
= (unsigned char*)certbuf
;
279 certitem
.len
= certlen
;
281 switch ( oiddata
->offset
) {
282 case SEC_OID_PKCS7_SIGNED_DATA
:
283 return(SEC_ReadPKCS7Certs(&certitem
, f
, arg
));
285 case SEC_OID_NS_TYPE_CERT_SEQUENCE
:
286 return(SEC_ReadCertSequence(&certitem
, f
, arg
));
293 /* it had better be a certificate by now!! */
294 certitem
.data
= (unsigned char*)certbuf
;
295 certitem
.len
= certlen
;
297 rv
= (* f
)(arg
, &pcertitem
, 1);
302 /* now look for a netscape base64 ascii encoded cert */
305 unsigned char *certbegin
= NULL
;
306 unsigned char *certend
= NULL
;
310 /* Convert the ASCII data into a nul-terminated string */
311 ascCert
= (char *)PORT_Alloc(certlen
+ 1);
317 PORT_Memcpy(ascCert
, certbuf
, certlen
);
318 ascCert
[certlen
] = '\0';
320 pc
= PORT_Strchr(ascCert
, '\n'); /* find an EOL */
321 if (!pc
) { /* maybe this is a MAC file */
323 while (*pc
&& NULL
!= (pc
= PORT_Strchr(pc
, '\r'))) {
328 cp
= (unsigned char *)ascCert
;
331 /* find the beginning marker */
332 while ( cl
> NS_CERT_HEADER_LEN
) {
334 if ( !PORT_Strncasecmp((char *)cp
, NS_CERT_HEADER
,
335 NS_CERT_HEADER_LEN
) ) {
336 cl
-= NS_CERT_HEADER_LEN
;
337 cp
+= NS_CERT_HEADER_LEN
;
341 /* skip to next eol */
342 while ( cl
&& ( *cp
!= '\n' )) {
347 /* skip all blank lines */
348 while ( cl
&& ( *cp
== '\n' || *cp
== '\r' )) {
359 /* find the ending marker */
360 while ( cl
>= NS_CERT_TRAILER_LEN
) {
361 if ( !PORT_Strncasecmp((char *)cp
, NS_CERT_TRAILER
,
362 NS_CERT_TRAILER_LEN
) ) {
363 certend
= (unsigned char *)cp
;
367 /* skip to next eol */
368 while ( cl
&& ( *cp
!= '\n' )) {
373 /* skip all blank lines */
374 while ( cl
&& ( *cp
== '\n' || *cp
== '\r' )) {
381 if ( certbegin
&& certend
) {
385 /* convert to binary */
386 bincert
= ATOB_AsciiToData(certbegin
, &binLen
);
392 /* now recurse to decode the binary */
393 rv
= CERT_DecodeCertPackage((char *)bincert
, binLen
, f
, arg
);
396 PORT_SetError(SEC_ERROR_BAD_DER
);
420 collect_certs(void *arg
, SECItem
**certs
, int numcerts
)
423 collect_args
*collectArgs
;
425 collectArgs
= (collect_args
*)arg
;
427 rv
= SECITEM_CopyItem(collectArgs
->arena
, &collectArgs
->cert
, *certs
);
434 * read an old style ascii or binary certificate
437 CERT_DecodeCertFromPackage(char *certbuf
, int certlen
)
439 collect_args collectArgs
;
441 CERTCertificate
*cert
= NULL
;
443 collectArgs
.arena
= PORT_NewArena(DER_DEFAULT_CHUNKSIZE
);
445 rv
= CERT_DecodeCertPackage(certbuf
, certlen
, collect_certs
,
446 (void *)&collectArgs
);
447 if ( rv
== SECSuccess
) {
448 cert
= CERT_NewTempCertificate(CERT_GetDefaultCertDB(),
449 &collectArgs
.cert
, NULL
,
453 PORT_FreeArena(collectArgs
.arena
, PR_FALSE
);