2 * Copyright (c) 2007, Cameron Rich
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are met:
9 * * Redistributions of source code must retain the above copyright notice,
10 * this list of conditions and the following disclaimer.
11 * * Redistributions in binary form must reproduce the above copyright notice,
12 * this list of conditions and the following disclaimer in the documentation
13 * and/or other materials provided with the distribution.
14 * * Neither the name of the axTLS project nor the names of its contributors
15 * may be used to endorse or promote products derived from this software
16 * without specific prior written permission.
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
22 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
23 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
25 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
26 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
27 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 * Certificate processing.
42 #include "crypto_misc.h"
44 #ifdef CONFIG_SSL_CERT_VERIFICATION
46 * Retrieve the signature from a certificate.
48 static const uint8_t *get_signature(const uint8_t *asn1_sig
, int *len
)
51 const uint8_t *ptr
= NULL
;
53 if (asn1_next_obj(asn1_sig
, &offset
, ASN1_SEQUENCE
) < 0 ||
54 asn1_skip_obj(asn1_sig
, &offset
, ASN1_SEQUENCE
))
57 if (asn1_sig
[offset
++] != ASN1_OCTET_STRING
)
59 *len
= get_asn1_length(asn1_sig
, &offset
);
60 ptr
= &asn1_sig
[offset
]; /* all ok */
69 * Construct a new x509 object.
70 * @return 0 if ok. < 0 if there was a problem.
72 int x509_new(const uint8_t *cert
, int *len
, X509_CTX
**ctx
)
74 int begin_tbs
, end_tbs
;
75 int ret
= X509_NOT_OK
, offset
= 0, cert_size
= 0;
79 *ctx
= (X509_CTX
*)calloc(1, sizeof(X509_CTX
));
82 /* get the certificate size */
83 asn1_skip_obj(cert
, &cert_size
, ASN1_SEQUENCE
);
85 if (asn1_next_obj(cert
, &offset
, ASN1_SEQUENCE
) < 0)
88 begin_tbs
= offset
; /* start of the tbs */
89 end_tbs
= begin_tbs
; /* work out the end of the tbs */
90 asn1_skip_obj(cert
, &end_tbs
, ASN1_SEQUENCE
);
92 if (asn1_next_obj(cert
, &offset
, ASN1_SEQUENCE
) < 0)
95 if (cert
[offset
] == ASN1_EXPLICIT_TAG
) /* optional version */
97 if (asn1_version(cert
, &offset
, x509_ctx
))
101 if (asn1_skip_obj(cert
, &offset
, ASN1_INTEGER
) || /* serial number */
102 asn1_next_obj(cert
, &offset
, ASN1_SEQUENCE
) < 0)
105 /* make sure the signature is ok */
106 if (asn1_signature_type(cert
, &offset
, x509_ctx
))
108 ret
= X509_VFY_ERROR_UNSUPPORTED_DIGEST
;
112 if (asn1_name(cert
, &offset
, x509_ctx
->ca_cert_dn
) ||
113 asn1_validity(cert
, &offset
, x509_ctx
) ||
114 asn1_name(cert
, &offset
, x509_ctx
->cert_dn
) ||
115 asn1_public_key(cert
, &offset
, x509_ctx
))
118 bi_ctx
= x509_ctx
->rsa_ctx
->bi_ctx
;
120 #ifdef CONFIG_SSL_CERT_VERIFICATION /* only care if doing verification */
121 /* use the appropriate signature algorithm (SHA1/MD5/MD2) */
122 if (x509_ctx
->sig_type
== SIG_TYPE_MD5
)
125 uint8_t md5_dgst
[MD5_SIZE
];
127 MD5_Update(&md5_ctx
, &cert
[begin_tbs
], end_tbs
-begin_tbs
);
128 MD5_Final(md5_dgst
, &md5_ctx
);
129 x509_ctx
->digest
= bi_import(bi_ctx
, md5_dgst
, MD5_SIZE
);
131 else if (x509_ctx
->sig_type
== SIG_TYPE_SHA1
)
134 uint8_t sha_dgst
[SHA1_SIZE
];
136 SHA1_Update(&sha_ctx
, &cert
[begin_tbs
], end_tbs
-begin_tbs
);
137 SHA1_Final(sha_dgst
, &sha_ctx
);
138 x509_ctx
->digest
= bi_import(bi_ctx
, sha_dgst
, SHA1_SIZE
);
140 else if (x509_ctx
->sig_type
== SIG_TYPE_MD2
)
143 uint8_t md2_dgst
[MD2_SIZE
];
145 MD2_Update(&md2_ctx
, &cert
[begin_tbs
], end_tbs
-begin_tbs
);
146 MD2_Final(md2_dgst
, &md2_ctx
);
147 x509_ctx
->digest
= bi_import(bi_ctx
, md2_dgst
, MD2_SIZE
);
150 offset
= end_tbs
; /* skip the v3 data */
151 if (asn1_skip_obj(cert
, &offset
, ASN1_SEQUENCE
) ||
152 asn1_signature(cert
, &offset
, x509_ctx
))
164 #ifdef CONFIG_SSL_FULL_MODE
167 printf("Error: Invalid X509 ASN.1 file\n");
175 * Free an X.509 object's resources.
177 void x509_free(X509_CTX
*x509_ctx
)
182 if (x509_ctx
== NULL
) /* if already null, then don't bother */
185 for (i
= 0; i
< X509_NUM_DN_TYPES
; i
++)
187 free(x509_ctx
->ca_cert_dn
[i
]);
188 free(x509_ctx
->cert_dn
[i
]);
191 free(x509_ctx
->signature
);
193 #ifdef CONFIG_SSL_CERT_VERIFICATION
194 if (x509_ctx
->digest
)
196 bi_free(x509_ctx
->rsa_ctx
->bi_ctx
, x509_ctx
->digest
);
200 RSA_free(x509_ctx
->rsa_ctx
);
202 next
= x509_ctx
->next
;
204 x509_free(next
); /* clear the chain */
207 #ifdef CONFIG_SSL_CERT_VERIFICATION
209 * Take a signature and decrypt it.
211 static bigint
*sig_verify(BI_CTX
*ctx
, const uint8_t *sig
, int sig_len
,
212 bigint
*modulus
, bigint
*pub_exp
)
215 bigint
*decrypted_bi
, *dat_bi
;
217 uint8_t *block
= (uint8_t *)alloca(sig_len
);
220 dat_bi
= bi_import(ctx
, sig
, sig_len
);
221 ctx
->mod_offset
= BIGINT_M_OFFSET
;
223 /* convert to a normal block */
224 decrypted_bi
= bi_mod_power2(ctx
, dat_bi
, modulus
, pub_exp
);
226 bi_export(ctx
, decrypted_bi
, block
, sig_len
);
227 ctx
->mod_offset
= BIGINT_M_OFFSET
;
229 i
= 10; /* start at the first possible non-padded byte */
230 while (block
[i
++] && i
< sig_len
);
233 /* get only the bit we want */
237 const uint8_t *sig_ptr
= get_signature(&block
[i
], &len
);
241 bir
= bi_import(ctx
, sig_ptr
, len
);
245 /* save a few bytes of memory */
251 * Do some basic checks on the certificate chain.
253 * Certificate verification consists of a number of checks:
254 * - The date of the certificate is after the start date.
255 * - The date of the certificate is before the finish date.
256 * - A root certificate exists in the certificate store.
257 * - That the certificate(s) are not self-signed.
258 * - The certificate chain is valid.
259 * - The signature of the certificate is valid.
261 int x509_verify(const CA_CERT_CTX
*ca_cert_ctx
, const X509_CTX
*cert
)
263 int ret
= X509_OK
, i
= 0;
265 X509_CTX
*next_cert
= NULL
;
267 bigint
*mod
= NULL
, *expn
= NULL
;
268 int match_ca_cert
= 0;
270 uint8_t is_self_signed
= 0;
274 ret
= X509_VFY_ERROR_NO_TRUSTED_CERT
;
278 /* a self-signed certificate that is not in the CA store - use this
279 to check the signature */
280 if (asn1_compare_dn(cert
->ca_cert_dn
, cert
->cert_dn
) == 0)
283 ctx
= cert
->rsa_ctx
->bi_ctx
;
284 mod
= cert
->rsa_ctx
->m
;
285 expn
= cert
->rsa_ctx
->e
;
288 gettimeofday(&tv
, NULL
);
290 /* check the not before date */
291 if (tv
.tv_sec
< cert
->not_before
)
293 ret
= X509_VFY_ERROR_NOT_YET_VALID
;
297 /* check the not after date */
298 if (tv
.tv_sec
> cert
->not_after
)
300 ret
= X509_VFY_ERROR_EXPIRED
;
304 next_cert
= cert
->next
;
306 /* last cert in the chain - look for a trusted cert */
307 if (next_cert
== NULL
)
309 if (ca_cert_ctx
!= NULL
)
311 /* go thu the CA store */
312 while (i
< CONFIG_X509_MAX_CA_CERTS
&& ca_cert_ctx
->cert
[i
])
314 if (asn1_compare_dn(cert
->ca_cert_dn
,
315 ca_cert_ctx
->cert
[i
]->cert_dn
) == 0)
317 /* use this CA certificate for signature verification */
319 ctx
= ca_cert_ctx
->cert
[i
]->rsa_ctx
->bi_ctx
;
320 mod
= ca_cert_ctx
->cert
[i
]->rsa_ctx
->m
;
321 expn
= ca_cert_ctx
->cert
[i
]->rsa_ctx
->e
;
329 /* couldn't find a trusted cert (& let self-signed errors be returned) */
330 if (!match_ca_cert
&& !is_self_signed
)
332 ret
= X509_VFY_ERROR_NO_TRUSTED_CERT
;
336 else if (asn1_compare_dn(cert
->ca_cert_dn
, next_cert
->cert_dn
) != 0)
338 /* check the chain */
339 ret
= X509_VFY_ERROR_INVALID_CHAIN
;
342 else /* use the next certificate in the chain for signature verify */
344 ctx
= next_cert
->rsa_ctx
->bi_ctx
;
345 mod
= next_cert
->rsa_ctx
->m
;
346 expn
= next_cert
->rsa_ctx
->e
;
349 /* cert is self signed */
350 if (!match_ca_cert
&& is_self_signed
)
352 ret
= X509_VFY_ERROR_SELF_SIGNED
;
356 /* check the signature */
357 cert_sig
= sig_verify(ctx
, cert
->signature
, cert
->sig_len
,
358 bi_clone(ctx
, mod
), bi_clone(ctx
, expn
));
360 if (cert_sig
&& cert
->digest
)
362 if (bi_compare(cert_sig
, cert
->digest
) != 0)
363 ret
= X509_VFY_ERROR_BAD_SIGNATURE
;
366 bi_free(ctx
, cert_sig
);
370 ret
= X509_VFY_ERROR_BAD_SIGNATURE
;
376 /* go down the certificate chain using recursion. */
377 if (next_cert
!= NULL
)
379 ret
= x509_verify(ca_cert_ctx
, next_cert
);
387 #if defined (CONFIG_SSL_FULL_MODE)
389 * Used for diagnostics.
391 static const char *not_part_of_cert
= "<Not Part Of Certificate>";
392 void x509_print(const X509_CTX
*cert
, CA_CERT_CTX
*ca_cert_ctx
)
397 printf("=== CERTIFICATE ISSUED TO ===\n");
398 printf("Common Name (CN):\t\t");
399 printf("%s\n", cert
->cert_dn
[X509_COMMON_NAME
] ?
400 cert
->cert_dn
[X509_COMMON_NAME
] : not_part_of_cert
);
402 printf("Organization (O):\t\t");
403 printf("%s\n", cert
->cert_dn
[X509_ORGANIZATION
] ?
404 cert
->cert_dn
[X509_ORGANIZATION
] : not_part_of_cert
);
406 printf("Organizational Unit (OU):\t");
407 printf("%s\n", cert
->cert_dn
[X509_ORGANIZATIONAL_UNIT
] ?
408 cert
->cert_dn
[X509_ORGANIZATIONAL_UNIT
] : not_part_of_cert
);
410 printf("=== CERTIFICATE ISSUED BY ===\n");
411 printf("Common Name (CN):\t\t");
412 printf("%s\n", cert
->ca_cert_dn
[X509_COMMON_NAME
] ?
413 cert
->ca_cert_dn
[X509_COMMON_NAME
] : not_part_of_cert
);
415 printf("Organization (O):\t\t");
416 printf("%s\n", cert
->ca_cert_dn
[X509_ORGANIZATION
] ?
417 cert
->ca_cert_dn
[X509_ORGANIZATION
] : not_part_of_cert
);
419 printf("Organizational Unit (OU):\t");
420 printf("%s\n", cert
->ca_cert_dn
[X509_ORGANIZATIONAL_UNIT
] ?
421 cert
->ca_cert_dn
[X509_ORGANIZATIONAL_UNIT
] : not_part_of_cert
);
423 printf("Not Before:\t\t\t%s", ctime(&cert
->not_before
));
424 printf("Not After:\t\t\t%s", ctime(&cert
->not_after
));
425 printf("RSA bitsize:\t\t\t%d\n", cert
->rsa_ctx
->num_octets
*8);
426 printf("Sig Type:\t\t\t");
427 switch (cert
->sig_type
)
439 printf("Unrecognized: %d\n", cert
->sig_type
);
445 printf("Verify:\t\t\t\t%s\n",
446 x509_display_error(x509_verify(ca_cert_ctx
, cert
)));
450 print_blob("Signature", cert
->signature
, cert
->sig_len
);
451 bi_print("Modulus", cert
->rsa_ctx
->m
);
452 bi_print("Pub Exp", cert
->rsa_ctx
->e
);
457 x509_print(cert
->next
, ca_cert_ctx
);
463 const char * x509_display_error(int error
)
468 return "Certificate verify successful";
471 return "X509 not ok";
473 case X509_VFY_ERROR_NO_TRUSTED_CERT
:
474 return "No trusted cert is available";
476 case X509_VFY_ERROR_BAD_SIGNATURE
:
477 return "Bad signature";
479 case X509_VFY_ERROR_NOT_YET_VALID
:
480 return "Cert is not yet valid";
482 case X509_VFY_ERROR_EXPIRED
:
483 return "Cert has expired";
485 case X509_VFY_ERROR_SELF_SIGNED
:
486 return "Cert is self-signed";
488 case X509_VFY_ERROR_INVALID_CHAIN
:
489 return "Chain is invalid (check order of certs)";
491 case X509_VFY_ERROR_UNSUPPORTED_DIGEST
:
492 return "Unsupported digest";
494 case X509_INVALID_PRIV_KEY
:
495 return "Invalid private key";
501 #endif /* CONFIG_SSL_FULL_MODE */