Rough and ready port of axTLS

Committer:
ashleymills
Date:
Mon May 13 18:15:18 2013 +0000
Revision:
0:5a29fd060ac8
initial commit

Who changed what in which revision?

UserRevisionLine numberNew contents of line
ashleymills 0:5a29fd060ac8 1 /*
ashleymills 0:5a29fd060ac8 2 * Copyright (c) 2007, Cameron Rich
ashleymills 0:5a29fd060ac8 3 *
ashleymills 0:5a29fd060ac8 4 * All rights reserved.
ashleymills 0:5a29fd060ac8 5 *
ashleymills 0:5a29fd060ac8 6 * Redistribution and use in source and binary forms, with or without
ashleymills 0:5a29fd060ac8 7 * modification, are permitted provided that the following conditions are met:
ashleymills 0:5a29fd060ac8 8 *
ashleymills 0:5a29fd060ac8 9 * * Redistributions of source code must retain the above copyright notice,
ashleymills 0:5a29fd060ac8 10 * this list of conditions and the following disclaimer.
ashleymills 0:5a29fd060ac8 11 * * Redistributions in binary form must reproduce the above copyright notice,
ashleymills 0:5a29fd060ac8 12 * this list of conditions and the following disclaimer in the documentation
ashleymills 0:5a29fd060ac8 13 * and/or other materials provided with the distribution.
ashleymills 0:5a29fd060ac8 14 * * Neither the name of the axTLS project nor the names of its contributors
ashleymills 0:5a29fd060ac8 15 * may be used to endorse or promote products derived from this software
ashleymills 0:5a29fd060ac8 16 * without specific prior written permission.
ashleymills 0:5a29fd060ac8 17 *
ashleymills 0:5a29fd060ac8 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
ashleymills 0:5a29fd060ac8 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
ashleymills 0:5a29fd060ac8 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
ashleymills 0:5a29fd060ac8 21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
ashleymills 0:5a29fd060ac8 22 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
ashleymills 0:5a29fd060ac8 23 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
ashleymills 0:5a29fd060ac8 24 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
ashleymills 0:5a29fd060ac8 25 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
ashleymills 0:5a29fd060ac8 26 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
ashleymills 0:5a29fd060ac8 27 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
ashleymills 0:5a29fd060ac8 28 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
ashleymills 0:5a29fd060ac8 29 */
ashleymills 0:5a29fd060ac8 30
ashleymills 0:5a29fd060ac8 31 /**
ashleymills 0:5a29fd060ac8 32 * Some primitive asn methods for extraction ASN.1 data.
ashleymills 0:5a29fd060ac8 33 */
ashleymills 0:5a29fd060ac8 34
ashleymills 0:5a29fd060ac8 35 #include <stdio.h>
ashleymills 0:5a29fd060ac8 36 #include <stdlib.h>
ashleymills 0:5a29fd060ac8 37 #include <string.h>
ashleymills 0:5a29fd060ac8 38 #include <time.h>
ashleymills 0:5a29fd060ac8 39 #include "os_port.h"
ashleymills 0:5a29fd060ac8 40 #include "crypto.h"
ashleymills 0:5a29fd060ac8 41 #include "crypto_misc.h"
ashleymills 0:5a29fd060ac8 42 #include "config.h"
ashleymills 0:5a29fd060ac8 43
ashleymills 0:5a29fd060ac8 44 #define SIG_OID_PREFIX_SIZE 8
ashleymills 0:5a29fd060ac8 45 #define SIG_IIS6_OID_SIZE 5
ashleymills 0:5a29fd060ac8 46 #define SIG_SUBJECT_ALT_NAME_SIZE 3
ashleymills 0:5a29fd060ac8 47
ashleymills 0:5a29fd060ac8 48 /* Must be an RSA algorithm with either SHA1 or MD5 for verifying to work */
ashleymills 0:5a29fd060ac8 49 static const uint8_t sig_oid_prefix[SIG_OID_PREFIX_SIZE] =
ashleymills 0:5a29fd060ac8 50 {
ashleymills 0:5a29fd060ac8 51 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01
ashleymills 0:5a29fd060ac8 52 };
ashleymills 0:5a29fd060ac8 53
ashleymills 0:5a29fd060ac8 54 static const uint8_t sig_sha1WithRSAEncrypt[SIG_IIS6_OID_SIZE] =
ashleymills 0:5a29fd060ac8 55 {
ashleymills 0:5a29fd060ac8 56 0x2b, 0x0e, 0x03, 0x02, 0x1d
ashleymills 0:5a29fd060ac8 57 };
ashleymills 0:5a29fd060ac8 58
ashleymills 0:5a29fd060ac8 59 static const uint8_t sig_subject_alt_name[SIG_SUBJECT_ALT_NAME_SIZE] =
ashleymills 0:5a29fd060ac8 60 {
ashleymills 0:5a29fd060ac8 61 0x55, 0x1d, 0x11
ashleymills 0:5a29fd060ac8 62 };
ashleymills 0:5a29fd060ac8 63
ashleymills 0:5a29fd060ac8 64 /* CN, O, OU */
ashleymills 0:5a29fd060ac8 65 static const uint8_t g_dn_types[] = { 3, 10, 11 };
ashleymills 0:5a29fd060ac8 66
ashleymills 0:5a29fd060ac8 67 int get_asn1_length(const uint8_t *buf, int *offset)
ashleymills 0:5a29fd060ac8 68 {
ashleymills 0:5a29fd060ac8 69 int len, i;
ashleymills 0:5a29fd060ac8 70
ashleymills 0:5a29fd060ac8 71 if (!(buf[*offset] & 0x80)) /* short form */
ashleymills 0:5a29fd060ac8 72 {
ashleymills 0:5a29fd060ac8 73 len = buf[(*offset)++];
ashleymills 0:5a29fd060ac8 74 }
ashleymills 0:5a29fd060ac8 75 else /* long form */
ashleymills 0:5a29fd060ac8 76 {
ashleymills 0:5a29fd060ac8 77 int length_bytes = buf[(*offset)++]&0x7f;
ashleymills 0:5a29fd060ac8 78 len = 0;
ashleymills 0:5a29fd060ac8 79 for (i = 0; i < length_bytes; i++)
ashleymills 0:5a29fd060ac8 80 {
ashleymills 0:5a29fd060ac8 81 len <<= 8;
ashleymills 0:5a29fd060ac8 82 len += buf[(*offset)++];
ashleymills 0:5a29fd060ac8 83 }
ashleymills 0:5a29fd060ac8 84 }
ashleymills 0:5a29fd060ac8 85
ashleymills 0:5a29fd060ac8 86 return len;
ashleymills 0:5a29fd060ac8 87 }
ashleymills 0:5a29fd060ac8 88
ashleymills 0:5a29fd060ac8 89 /**
ashleymills 0:5a29fd060ac8 90 * Skip the ASN1.1 object type and its length. Get ready to read the object's
ashleymills 0:5a29fd060ac8 91 * data.
ashleymills 0:5a29fd060ac8 92 */
ashleymills 0:5a29fd060ac8 93 int asn1_next_obj(const uint8_t *buf, int *offset, int obj_type)
ashleymills 0:5a29fd060ac8 94 {
ashleymills 0:5a29fd060ac8 95 if (buf[*offset] != obj_type)
ashleymills 0:5a29fd060ac8 96 return X509_NOT_OK;
ashleymills 0:5a29fd060ac8 97 (*offset)++;
ashleymills 0:5a29fd060ac8 98 return get_asn1_length(buf, offset);
ashleymills 0:5a29fd060ac8 99 }
ashleymills 0:5a29fd060ac8 100
ashleymills 0:5a29fd060ac8 101 /**
ashleymills 0:5a29fd060ac8 102 * Skip over an ASN.1 object type completely. Get ready to read the next
ashleymills 0:5a29fd060ac8 103 * object.
ashleymills 0:5a29fd060ac8 104 */
ashleymills 0:5a29fd060ac8 105 int asn1_skip_obj(const uint8_t *buf, int *offset, int obj_type)
ashleymills 0:5a29fd060ac8 106 {
ashleymills 0:5a29fd060ac8 107 int len;
ashleymills 0:5a29fd060ac8 108
ashleymills 0:5a29fd060ac8 109 if (buf[*offset] != obj_type)
ashleymills 0:5a29fd060ac8 110 return X509_NOT_OK;
ashleymills 0:5a29fd060ac8 111 (*offset)++;
ashleymills 0:5a29fd060ac8 112 len = get_asn1_length(buf, offset);
ashleymills 0:5a29fd060ac8 113 *offset += len;
ashleymills 0:5a29fd060ac8 114 return 0;
ashleymills 0:5a29fd060ac8 115 }
ashleymills 0:5a29fd060ac8 116
ashleymills 0:5a29fd060ac8 117 /**
ashleymills 0:5a29fd060ac8 118 * Read an integer value for ASN.1 data
ashleymills 0:5a29fd060ac8 119 * Note: This function allocates memory which must be freed by the user.
ashleymills 0:5a29fd060ac8 120 */
ashleymills 0:5a29fd060ac8 121 int asn1_get_int(const uint8_t *buf, int *offset, uint8_t **object)
ashleymills 0:5a29fd060ac8 122 {
ashleymills 0:5a29fd060ac8 123 int len;
ashleymills 0:5a29fd060ac8 124
ashleymills 0:5a29fd060ac8 125 if ((len = asn1_next_obj(buf, offset, ASN1_INTEGER)) < 0)
ashleymills 0:5a29fd060ac8 126 goto end_int_array;
ashleymills 0:5a29fd060ac8 127
ashleymills 0:5a29fd060ac8 128 if (len > 1 && buf[*offset] == 0x00) /* ignore the negative byte */
ashleymills 0:5a29fd060ac8 129 {
ashleymills 0:5a29fd060ac8 130 len--;
ashleymills 0:5a29fd060ac8 131 (*offset)++;
ashleymills 0:5a29fd060ac8 132 }
ashleymills 0:5a29fd060ac8 133
ashleymills 0:5a29fd060ac8 134 *object = (uint8_t *)malloc(len);
ashleymills 0:5a29fd060ac8 135 memcpy(*object, &buf[*offset], len);
ashleymills 0:5a29fd060ac8 136 *offset += len;
ashleymills 0:5a29fd060ac8 137
ashleymills 0:5a29fd060ac8 138 end_int_array:
ashleymills 0:5a29fd060ac8 139 return len;
ashleymills 0:5a29fd060ac8 140 }
ashleymills 0:5a29fd060ac8 141
ashleymills 0:5a29fd060ac8 142 /**
ashleymills 0:5a29fd060ac8 143 * Get all the RSA private key specifics from an ASN.1 encoded file
ashleymills 0:5a29fd060ac8 144 */
ashleymills 0:5a29fd060ac8 145 int asn1_get_private_key(const uint8_t *buf, int len, RSA_CTX **rsa_ctx)
ashleymills 0:5a29fd060ac8 146 {
ashleymills 0:5a29fd060ac8 147 int offset = 7;
ashleymills 0:5a29fd060ac8 148 uint8_t *modulus = NULL, *priv_exp = NULL, *pub_exp = NULL;
ashleymills 0:5a29fd060ac8 149 int mod_len, priv_len, pub_len;
ashleymills 0:5a29fd060ac8 150 #ifdef CONFIG_BIGINT_CRT
ashleymills 0:5a29fd060ac8 151 uint8_t *p = NULL, *q = NULL, *dP = NULL, *dQ = NULL, *qInv = NULL;
ashleymills 0:5a29fd060ac8 152 int p_len, q_len, dP_len, dQ_len, qInv_len;
ashleymills 0:5a29fd060ac8 153 #endif
ashleymills 0:5a29fd060ac8 154
ashleymills 0:5a29fd060ac8 155 /* not in der format */
ashleymills 0:5a29fd060ac8 156 if (buf[0] != ASN1_SEQUENCE) /* basic sanity check */
ashleymills 0:5a29fd060ac8 157 {
ashleymills 0:5a29fd060ac8 158 #ifdef CONFIG_SSL_FULL_MODE
ashleymills 0:5a29fd060ac8 159 printf("Error: This is not a valid ASN.1 file\n");
ashleymills 0:5a29fd060ac8 160 #endif
ashleymills 0:5a29fd060ac8 161 return X509_INVALID_PRIV_KEY;
ashleymills 0:5a29fd060ac8 162 }
ashleymills 0:5a29fd060ac8 163
ashleymills 0:5a29fd060ac8 164 /* Use the private key to mix up the RNG if possible. */
ashleymills 0:5a29fd060ac8 165 RNG_custom_init(buf, len);
ashleymills 0:5a29fd060ac8 166
ashleymills 0:5a29fd060ac8 167 mod_len = asn1_get_int(buf, &offset, &modulus);
ashleymills 0:5a29fd060ac8 168 pub_len = asn1_get_int(buf, &offset, &pub_exp);
ashleymills 0:5a29fd060ac8 169 priv_len = asn1_get_int(buf, &offset, &priv_exp);
ashleymills 0:5a29fd060ac8 170
ashleymills 0:5a29fd060ac8 171 if (mod_len <= 0 || pub_len <= 0 || priv_len <= 0)
ashleymills 0:5a29fd060ac8 172 return X509_INVALID_PRIV_KEY;
ashleymills 0:5a29fd060ac8 173
ashleymills 0:5a29fd060ac8 174 #ifdef CONFIG_BIGINT_CRT
ashleymills 0:5a29fd060ac8 175 p_len = asn1_get_int(buf, &offset, &p);
ashleymills 0:5a29fd060ac8 176 q_len = asn1_get_int(buf, &offset, &q);
ashleymills 0:5a29fd060ac8 177 dP_len = asn1_get_int(buf, &offset, &dP);
ashleymills 0:5a29fd060ac8 178 dQ_len = asn1_get_int(buf, &offset, &dQ);
ashleymills 0:5a29fd060ac8 179 qInv_len = asn1_get_int(buf, &offset, &qInv);
ashleymills 0:5a29fd060ac8 180
ashleymills 0:5a29fd060ac8 181 if (p_len <= 0 || q_len <= 0 || dP_len <= 0 || dQ_len <= 0 || qInv_len <= 0)
ashleymills 0:5a29fd060ac8 182 return X509_INVALID_PRIV_KEY;
ashleymills 0:5a29fd060ac8 183
ashleymills 0:5a29fd060ac8 184 RSA_priv_key_new(rsa_ctx,
ashleymills 0:5a29fd060ac8 185 modulus, mod_len, pub_exp, pub_len, priv_exp, priv_len,
ashleymills 0:5a29fd060ac8 186 p, p_len, q, p_len, dP, dP_len, dQ, dQ_len, qInv, qInv_len);
ashleymills 0:5a29fd060ac8 187
ashleymills 0:5a29fd060ac8 188 free(p);
ashleymills 0:5a29fd060ac8 189 free(q);
ashleymills 0:5a29fd060ac8 190 free(dP);
ashleymills 0:5a29fd060ac8 191 free(dQ);
ashleymills 0:5a29fd060ac8 192 free(qInv);
ashleymills 0:5a29fd060ac8 193 #else
ashleymills 0:5a29fd060ac8 194 RSA_priv_key_new(rsa_ctx,
ashleymills 0:5a29fd060ac8 195 modulus, mod_len, pub_exp, pub_len, priv_exp, priv_len);
ashleymills 0:5a29fd060ac8 196 #endif
ashleymills 0:5a29fd060ac8 197
ashleymills 0:5a29fd060ac8 198 free(modulus);
ashleymills 0:5a29fd060ac8 199 free(priv_exp);
ashleymills 0:5a29fd060ac8 200 free(pub_exp);
ashleymills 0:5a29fd060ac8 201 return X509_OK;
ashleymills 0:5a29fd060ac8 202 }
ashleymills 0:5a29fd060ac8 203
ashleymills 0:5a29fd060ac8 204 /**
ashleymills 0:5a29fd060ac8 205 * Get the time of a certificate. Ignore hours/minutes/seconds.
ashleymills 0:5a29fd060ac8 206 */
ashleymills 0:5a29fd060ac8 207 static int asn1_get_utc_time(const uint8_t *buf, int *offset, time_t *t)
ashleymills 0:5a29fd060ac8 208 {
ashleymills 0:5a29fd060ac8 209 int ret = X509_NOT_OK, len, t_offset;
ashleymills 0:5a29fd060ac8 210 struct tm tm;
ashleymills 0:5a29fd060ac8 211
ashleymills 0:5a29fd060ac8 212 if (buf[(*offset)++] != ASN1_UTC_TIME)
ashleymills 0:5a29fd060ac8 213 goto end_utc_time;
ashleymills 0:5a29fd060ac8 214
ashleymills 0:5a29fd060ac8 215 len = get_asn1_length(buf, offset);
ashleymills 0:5a29fd060ac8 216 t_offset = *offset;
ashleymills 0:5a29fd060ac8 217
ashleymills 0:5a29fd060ac8 218 memset(&tm, 0, sizeof(struct tm));
ashleymills 0:5a29fd060ac8 219 tm.tm_year = (buf[t_offset] - '0')*10 + (buf[t_offset+1] - '0');
ashleymills 0:5a29fd060ac8 220
ashleymills 0:5a29fd060ac8 221 if (tm.tm_year <= 50) /* 1951-2050 thing */
ashleymills 0:5a29fd060ac8 222 {
ashleymills 0:5a29fd060ac8 223 tm.tm_year += 100;
ashleymills 0:5a29fd060ac8 224 }
ashleymills 0:5a29fd060ac8 225
ashleymills 0:5a29fd060ac8 226 tm.tm_mon = (buf[t_offset+2] - '0')*10 + (buf[t_offset+3] - '0') - 1;
ashleymills 0:5a29fd060ac8 227 tm.tm_mday = (buf[t_offset+4] - '0')*10 + (buf[t_offset+5] - '0');
ashleymills 0:5a29fd060ac8 228 *t = mktime(&tm);
ashleymills 0:5a29fd060ac8 229 *offset += len;
ashleymills 0:5a29fd060ac8 230 ret = X509_OK;
ashleymills 0:5a29fd060ac8 231
ashleymills 0:5a29fd060ac8 232 end_utc_time:
ashleymills 0:5a29fd060ac8 233 return ret;
ashleymills 0:5a29fd060ac8 234 }
ashleymills 0:5a29fd060ac8 235
ashleymills 0:5a29fd060ac8 236 /**
ashleymills 0:5a29fd060ac8 237 * Get the version type of a certificate (which we don't actually care about)
ashleymills 0:5a29fd060ac8 238 */
ashleymills 0:5a29fd060ac8 239 int asn1_version(const uint8_t *cert, int *offset, X509_CTX *x509_ctx)
ashleymills 0:5a29fd060ac8 240 {
ashleymills 0:5a29fd060ac8 241 int ret = X509_NOT_OK;
ashleymills 0:5a29fd060ac8 242
ashleymills 0:5a29fd060ac8 243 (*offset) += 2; /* get past explicit tag */
ashleymills 0:5a29fd060ac8 244 if (asn1_skip_obj(cert, offset, ASN1_INTEGER))
ashleymills 0:5a29fd060ac8 245 goto end_version;
ashleymills 0:5a29fd060ac8 246
ashleymills 0:5a29fd060ac8 247 ret = X509_OK;
ashleymills 0:5a29fd060ac8 248 end_version:
ashleymills 0:5a29fd060ac8 249 return ret;
ashleymills 0:5a29fd060ac8 250 }
ashleymills 0:5a29fd060ac8 251
ashleymills 0:5a29fd060ac8 252 /**
ashleymills 0:5a29fd060ac8 253 * Retrieve the notbefore and notafter certificate times.
ashleymills 0:5a29fd060ac8 254 */
ashleymills 0:5a29fd060ac8 255 int asn1_validity(const uint8_t *cert, int *offset, X509_CTX *x509_ctx)
ashleymills 0:5a29fd060ac8 256 {
ashleymills 0:5a29fd060ac8 257 return (asn1_next_obj(cert, offset, ASN1_SEQUENCE) < 0 ||
ashleymills 0:5a29fd060ac8 258 asn1_get_utc_time(cert, offset, &x509_ctx->not_before) ||
ashleymills 0:5a29fd060ac8 259 asn1_get_utc_time(cert, offset, &x509_ctx->not_after));
ashleymills 0:5a29fd060ac8 260 }
ashleymills 0:5a29fd060ac8 261
ashleymills 0:5a29fd060ac8 262 /**
ashleymills 0:5a29fd060ac8 263 * Get the components of a distinguished name
ashleymills 0:5a29fd060ac8 264 */
ashleymills 0:5a29fd060ac8 265 static int asn1_get_oid_x520(const uint8_t *buf, int *offset)
ashleymills 0:5a29fd060ac8 266 {
ashleymills 0:5a29fd060ac8 267 int dn_type = 0;
ashleymills 0:5a29fd060ac8 268 int len;
ashleymills 0:5a29fd060ac8 269
ashleymills 0:5a29fd060ac8 270 if ((len = asn1_next_obj(buf, offset, ASN1_OID)) < 0)
ashleymills 0:5a29fd060ac8 271 goto end_oid;
ashleymills 0:5a29fd060ac8 272
ashleymills 0:5a29fd060ac8 273 /* expect a sequence of 2.5.4.[x] where x is a one of distinguished name
ashleymills 0:5a29fd060ac8 274 components we are interested in. */
ashleymills 0:5a29fd060ac8 275 if (len == 3 && buf[(*offset)++] == 0x55 && buf[(*offset)++] == 0x04)
ashleymills 0:5a29fd060ac8 276 dn_type = buf[(*offset)++];
ashleymills 0:5a29fd060ac8 277 else
ashleymills 0:5a29fd060ac8 278 {
ashleymills 0:5a29fd060ac8 279 *offset += len; /* skip over it */
ashleymills 0:5a29fd060ac8 280 }
ashleymills 0:5a29fd060ac8 281
ashleymills 0:5a29fd060ac8 282 end_oid:
ashleymills 0:5a29fd060ac8 283 return dn_type;
ashleymills 0:5a29fd060ac8 284 }
ashleymills 0:5a29fd060ac8 285
ashleymills 0:5a29fd060ac8 286 /**
ashleymills 0:5a29fd060ac8 287 * Obtain an ASN.1 printable string type.
ashleymills 0:5a29fd060ac8 288 */
ashleymills 0:5a29fd060ac8 289 static int asn1_get_printable_str(const uint8_t *buf, int *offset, char **str)
ashleymills 0:5a29fd060ac8 290 {
ashleymills 0:5a29fd060ac8 291 int len = X509_NOT_OK;
ashleymills 0:5a29fd060ac8 292 int asn1_type = buf[*offset];
ashleymills 0:5a29fd060ac8 293
ashleymills 0:5a29fd060ac8 294 /* some certs have this awful crud in them for some reason */
ashleymills 0:5a29fd060ac8 295 if (asn1_type != ASN1_PRINTABLE_STR &&
ashleymills 0:5a29fd060ac8 296 asn1_type != ASN1_PRINTABLE_STR2 &&
ashleymills 0:5a29fd060ac8 297 asn1_type != ASN1_TELETEX_STR &&
ashleymills 0:5a29fd060ac8 298 asn1_type != ASN1_IA5_STR &&
ashleymills 0:5a29fd060ac8 299 asn1_type != ASN1_UNICODE_STR)
ashleymills 0:5a29fd060ac8 300 goto end_pnt_str;
ashleymills 0:5a29fd060ac8 301
ashleymills 0:5a29fd060ac8 302 (*offset)++;
ashleymills 0:5a29fd060ac8 303 len = get_asn1_length(buf, offset);
ashleymills 0:5a29fd060ac8 304
ashleymills 0:5a29fd060ac8 305 if (asn1_type == ASN1_UNICODE_STR)
ashleymills 0:5a29fd060ac8 306 {
ashleymills 0:5a29fd060ac8 307 int i;
ashleymills 0:5a29fd060ac8 308 *str = (char *)malloc(len/2+1); /* allow for null */
ashleymills 0:5a29fd060ac8 309
ashleymills 0:5a29fd060ac8 310 for (i = 0; i < len; i += 2)
ashleymills 0:5a29fd060ac8 311 (*str)[i/2] = buf[*offset + i + 1];
ashleymills 0:5a29fd060ac8 312
ashleymills 0:5a29fd060ac8 313 (*str)[len/2] = 0; /* null terminate */
ashleymills 0:5a29fd060ac8 314 }
ashleymills 0:5a29fd060ac8 315 else
ashleymills 0:5a29fd060ac8 316 {
ashleymills 0:5a29fd060ac8 317 *str = (char *)malloc(len+1); /* allow for null */
ashleymills 0:5a29fd060ac8 318 memcpy(*str, &buf[*offset], len);
ashleymills 0:5a29fd060ac8 319 (*str)[len] = 0; /* null terminate */
ashleymills 0:5a29fd060ac8 320 }
ashleymills 0:5a29fd060ac8 321
ashleymills 0:5a29fd060ac8 322 *offset += len;
ashleymills 0:5a29fd060ac8 323
ashleymills 0:5a29fd060ac8 324 end_pnt_str:
ashleymills 0:5a29fd060ac8 325 return len;
ashleymills 0:5a29fd060ac8 326 }
ashleymills 0:5a29fd060ac8 327
ashleymills 0:5a29fd060ac8 328 /**
ashleymills 0:5a29fd060ac8 329 * Get the subject name (or the issuer) of a certificate.
ashleymills 0:5a29fd060ac8 330 */
ashleymills 0:5a29fd060ac8 331 int asn1_name(const uint8_t *cert, int *offset, char *dn[])
ashleymills 0:5a29fd060ac8 332 {
ashleymills 0:5a29fd060ac8 333 int ret = X509_NOT_OK;
ashleymills 0:5a29fd060ac8 334 int dn_type;
ashleymills 0:5a29fd060ac8 335 char *tmp;
ashleymills 0:5a29fd060ac8 336
ashleymills 0:5a29fd060ac8 337 if (asn1_next_obj(cert, offset, ASN1_SEQUENCE) < 0)
ashleymills 0:5a29fd060ac8 338 goto end_name;
ashleymills 0:5a29fd060ac8 339
ashleymills 0:5a29fd060ac8 340 while (asn1_next_obj(cert, offset, ASN1_SET) >= 0)
ashleymills 0:5a29fd060ac8 341 {
ashleymills 0:5a29fd060ac8 342 int i, found = 0;
ashleymills 0:5a29fd060ac8 343
ashleymills 0:5a29fd060ac8 344 if (asn1_next_obj(cert, offset, ASN1_SEQUENCE) < 0 ||
ashleymills 0:5a29fd060ac8 345 (dn_type = asn1_get_oid_x520(cert, offset)) < 0)
ashleymills 0:5a29fd060ac8 346 goto end_name;
ashleymills 0:5a29fd060ac8 347
ashleymills 0:5a29fd060ac8 348 tmp = NULL;
ashleymills 0:5a29fd060ac8 349
ashleymills 0:5a29fd060ac8 350 if (asn1_get_printable_str(cert, offset, &tmp) < 0)
ashleymills 0:5a29fd060ac8 351 {
ashleymills 0:5a29fd060ac8 352 free(tmp);
ashleymills 0:5a29fd060ac8 353 goto end_name;
ashleymills 0:5a29fd060ac8 354 }
ashleymills 0:5a29fd060ac8 355
ashleymills 0:5a29fd060ac8 356 /* find the distinguished named type */
ashleymills 0:5a29fd060ac8 357 for (i = 0; i < X509_NUM_DN_TYPES; i++)
ashleymills 0:5a29fd060ac8 358 {
ashleymills 0:5a29fd060ac8 359 if (dn_type == g_dn_types[i])
ashleymills 0:5a29fd060ac8 360 {
ashleymills 0:5a29fd060ac8 361 if (dn[i] == NULL)
ashleymills 0:5a29fd060ac8 362 {
ashleymills 0:5a29fd060ac8 363 dn[i] = tmp;
ashleymills 0:5a29fd060ac8 364 found = 1;
ashleymills 0:5a29fd060ac8 365 break;
ashleymills 0:5a29fd060ac8 366 }
ashleymills 0:5a29fd060ac8 367 }
ashleymills 0:5a29fd060ac8 368 }
ashleymills 0:5a29fd060ac8 369
ashleymills 0:5a29fd060ac8 370 if (found == 0) /* not found so get rid of it */
ashleymills 0:5a29fd060ac8 371 {
ashleymills 0:5a29fd060ac8 372 free(tmp);
ashleymills 0:5a29fd060ac8 373 }
ashleymills 0:5a29fd060ac8 374 }
ashleymills 0:5a29fd060ac8 375
ashleymills 0:5a29fd060ac8 376 ret = X509_OK;
ashleymills 0:5a29fd060ac8 377 end_name:
ashleymills 0:5a29fd060ac8 378 return ret;
ashleymills 0:5a29fd060ac8 379 }
ashleymills 0:5a29fd060ac8 380
ashleymills 0:5a29fd060ac8 381 /**
ashleymills 0:5a29fd060ac8 382 * Read the modulus and public exponent of a certificate.
ashleymills 0:5a29fd060ac8 383 */
ashleymills 0:5a29fd060ac8 384 int asn1_public_key(const uint8_t *cert, int *offset, X509_CTX *x509_ctx)
ashleymills 0:5a29fd060ac8 385 {
ashleymills 0:5a29fd060ac8 386 int ret = X509_NOT_OK, mod_len, pub_len;
ashleymills 0:5a29fd060ac8 387 uint8_t *modulus = NULL, *pub_exp = NULL;
ashleymills 0:5a29fd060ac8 388
ashleymills 0:5a29fd060ac8 389 if (asn1_next_obj(cert, offset, ASN1_SEQUENCE) < 0 ||
ashleymills 0:5a29fd060ac8 390 asn1_skip_obj(cert, offset, ASN1_SEQUENCE) ||
ashleymills 0:5a29fd060ac8 391 asn1_next_obj(cert, offset, ASN1_BIT_STRING) < 0)
ashleymills 0:5a29fd060ac8 392 goto end_pub_key;
ashleymills 0:5a29fd060ac8 393
ashleymills 0:5a29fd060ac8 394 (*offset)++; /* ignore the padding bit field */
ashleymills 0:5a29fd060ac8 395
ashleymills 0:5a29fd060ac8 396 if (asn1_next_obj(cert, offset, ASN1_SEQUENCE) < 0)
ashleymills 0:5a29fd060ac8 397 goto end_pub_key;
ashleymills 0:5a29fd060ac8 398
ashleymills 0:5a29fd060ac8 399 mod_len = asn1_get_int(cert, offset, &modulus);
ashleymills 0:5a29fd060ac8 400 pub_len = asn1_get_int(cert, offset, &pub_exp);
ashleymills 0:5a29fd060ac8 401
ashleymills 0:5a29fd060ac8 402 RSA_pub_key_new(&x509_ctx->rsa_ctx, modulus, mod_len, pub_exp, pub_len);
ashleymills 0:5a29fd060ac8 403
ashleymills 0:5a29fd060ac8 404 free(modulus);
ashleymills 0:5a29fd060ac8 405 free(pub_exp);
ashleymills 0:5a29fd060ac8 406 ret = X509_OK;
ashleymills 0:5a29fd060ac8 407
ashleymills 0:5a29fd060ac8 408 end_pub_key:
ashleymills 0:5a29fd060ac8 409 return ret;
ashleymills 0:5a29fd060ac8 410 }
ashleymills 0:5a29fd060ac8 411
ashleymills 0:5a29fd060ac8 412 #ifdef CONFIG_SSL_CERT_VERIFICATION
ashleymills 0:5a29fd060ac8 413 /**
ashleymills 0:5a29fd060ac8 414 * Read the signature of the certificate.
ashleymills 0:5a29fd060ac8 415 */
ashleymills 0:5a29fd060ac8 416 int asn1_signature(const uint8_t *cert, int *offset, X509_CTX *x509_ctx)
ashleymills 0:5a29fd060ac8 417 {
ashleymills 0:5a29fd060ac8 418 int ret = X509_NOT_OK;
ashleymills 0:5a29fd060ac8 419
ashleymills 0:5a29fd060ac8 420 if (cert[(*offset)++] != ASN1_BIT_STRING)
ashleymills 0:5a29fd060ac8 421 goto end_sig;
ashleymills 0:5a29fd060ac8 422
ashleymills 0:5a29fd060ac8 423 x509_ctx->sig_len = get_asn1_length(cert, offset)-1;
ashleymills 0:5a29fd060ac8 424 (*offset)++; /* ignore bit string padding bits */
ashleymills 0:5a29fd060ac8 425 x509_ctx->signature = (uint8_t *)malloc(x509_ctx->sig_len);
ashleymills 0:5a29fd060ac8 426 memcpy(x509_ctx->signature, &cert[*offset], x509_ctx->sig_len);
ashleymills 0:5a29fd060ac8 427 *offset += x509_ctx->sig_len;
ashleymills 0:5a29fd060ac8 428 ret = X509_OK;
ashleymills 0:5a29fd060ac8 429
ashleymills 0:5a29fd060ac8 430 end_sig:
ashleymills 0:5a29fd060ac8 431 return ret;
ashleymills 0:5a29fd060ac8 432 }
ashleymills 0:5a29fd060ac8 433
ashleymills 0:5a29fd060ac8 434 /*
ashleymills 0:5a29fd060ac8 435 * Compare 2 distinguished name components for equality
ashleymills 0:5a29fd060ac8 436 * @return 0 if a match
ashleymills 0:5a29fd060ac8 437 */
ashleymills 0:5a29fd060ac8 438 static int asn1_compare_dn_comp(const char *dn1, const char *dn2)
ashleymills 0:5a29fd060ac8 439 {
ashleymills 0:5a29fd060ac8 440 int ret;
ashleymills 0:5a29fd060ac8 441
ashleymills 0:5a29fd060ac8 442 if (dn1 == NULL && dn2 == NULL)
ashleymills 0:5a29fd060ac8 443 ret = 0;
ashleymills 0:5a29fd060ac8 444 else
ashleymills 0:5a29fd060ac8 445 ret = (dn1 && dn2) ? strcmp(dn1, dn2) : 1;
ashleymills 0:5a29fd060ac8 446
ashleymills 0:5a29fd060ac8 447 return ret;
ashleymills 0:5a29fd060ac8 448 }
ashleymills 0:5a29fd060ac8 449
ashleymills 0:5a29fd060ac8 450 /**
ashleymills 0:5a29fd060ac8 451 * Clean up all of the CA certificates.
ashleymills 0:5a29fd060ac8 452 */
ashleymills 0:5a29fd060ac8 453 void remove_ca_certs(CA_CERT_CTX *ca_cert_ctx)
ashleymills 0:5a29fd060ac8 454 {
ashleymills 0:5a29fd060ac8 455 int i = 0;
ashleymills 0:5a29fd060ac8 456
ashleymills 0:5a29fd060ac8 457 if (ca_cert_ctx == NULL)
ashleymills 0:5a29fd060ac8 458 return;
ashleymills 0:5a29fd060ac8 459
ashleymills 0:5a29fd060ac8 460 while (i < CONFIG_X509_MAX_CA_CERTS && ca_cert_ctx->cert[i])
ashleymills 0:5a29fd060ac8 461 {
ashleymills 0:5a29fd060ac8 462 x509_free(ca_cert_ctx->cert[i]);
ashleymills 0:5a29fd060ac8 463 ca_cert_ctx->cert[i++] = NULL;
ashleymills 0:5a29fd060ac8 464 }
ashleymills 0:5a29fd060ac8 465
ashleymills 0:5a29fd060ac8 466 free(ca_cert_ctx);
ashleymills 0:5a29fd060ac8 467 }
ashleymills 0:5a29fd060ac8 468
ashleymills 0:5a29fd060ac8 469 /*
ashleymills 0:5a29fd060ac8 470 * Compare 2 distinguished names for equality
ashleymills 0:5a29fd060ac8 471 * @return 0 if a match
ashleymills 0:5a29fd060ac8 472 */
ashleymills 0:5a29fd060ac8 473 int asn1_compare_dn(char * const dn1[], char * const dn2[])
ashleymills 0:5a29fd060ac8 474 {
ashleymills 0:5a29fd060ac8 475 int i;
ashleymills 0:5a29fd060ac8 476
ashleymills 0:5a29fd060ac8 477 for (i = 0; i < X509_NUM_DN_TYPES; i++)
ashleymills 0:5a29fd060ac8 478 {
ashleymills 0:5a29fd060ac8 479 if (asn1_compare_dn_comp(dn1[i], dn2[i]))
ashleymills 0:5a29fd060ac8 480 return 1;
ashleymills 0:5a29fd060ac8 481 }
ashleymills 0:5a29fd060ac8 482
ashleymills 0:5a29fd060ac8 483 return 0; /* all good */
ashleymills 0:5a29fd060ac8 484 }
ashleymills 0:5a29fd060ac8 485
ashleymills 0:5a29fd060ac8 486 int asn1_find_oid(const uint8_t* cert, int* offset,
ashleymills 0:5a29fd060ac8 487 const uint8_t* oid, int oid_length)
ashleymills 0:5a29fd060ac8 488 {
ashleymills 0:5a29fd060ac8 489 int seqlen;
ashleymills 0:5a29fd060ac8 490 if ((seqlen = asn1_next_obj(cert, offset, ASN1_SEQUENCE))> 0)
ashleymills 0:5a29fd060ac8 491 {
ashleymills 0:5a29fd060ac8 492 int end = *offset + seqlen;
ashleymills 0:5a29fd060ac8 493
ashleymills 0:5a29fd060ac8 494 while (*offset < end)
ashleymills 0:5a29fd060ac8 495 {
ashleymills 0:5a29fd060ac8 496 int type = cert[(*offset)++];
ashleymills 0:5a29fd060ac8 497 int length = get_asn1_length(cert, offset);
ashleymills 0:5a29fd060ac8 498 int noffset = *offset + length;
ashleymills 0:5a29fd060ac8 499
ashleymills 0:5a29fd060ac8 500 if (type == ASN1_SEQUENCE)
ashleymills 0:5a29fd060ac8 501 {
ashleymills 0:5a29fd060ac8 502 type = cert[(*offset)++];
ashleymills 0:5a29fd060ac8 503 length = get_asn1_length(cert, offset);
ashleymills 0:5a29fd060ac8 504
ashleymills 0:5a29fd060ac8 505 if (type == ASN1_OID && length == oid_length &&
ashleymills 0:5a29fd060ac8 506 memcmp(cert + *offset, oid, oid_length) == 0)
ashleymills 0:5a29fd060ac8 507 {
ashleymills 0:5a29fd060ac8 508 *offset += oid_length;
ashleymills 0:5a29fd060ac8 509 return 1;
ashleymills 0:5a29fd060ac8 510 }
ashleymills 0:5a29fd060ac8 511 }
ashleymills 0:5a29fd060ac8 512
ashleymills 0:5a29fd060ac8 513 *offset = noffset;
ashleymills 0:5a29fd060ac8 514 }
ashleymills 0:5a29fd060ac8 515 }
ashleymills 0:5a29fd060ac8 516
ashleymills 0:5a29fd060ac8 517 return 0;
ashleymills 0:5a29fd060ac8 518 }
ashleymills 0:5a29fd060ac8 519
ashleymills 0:5a29fd060ac8 520 int asn1_find_subjectaltname(const uint8_t* cert, int offset)
ashleymills 0:5a29fd060ac8 521 {
ashleymills 0:5a29fd060ac8 522 if (asn1_find_oid(cert, &offset, sig_subject_alt_name,
ashleymills 0:5a29fd060ac8 523 SIG_SUBJECT_ALT_NAME_SIZE))
ashleymills 0:5a29fd060ac8 524 {
ashleymills 0:5a29fd060ac8 525 return offset;
ashleymills 0:5a29fd060ac8 526 }
ashleymills 0:5a29fd060ac8 527
ashleymills 0:5a29fd060ac8 528 return 0;
ashleymills 0:5a29fd060ac8 529 }
ashleymills 0:5a29fd060ac8 530
ashleymills 0:5a29fd060ac8 531 #endif /* CONFIG_SSL_CERT_VERIFICATION */
ashleymills 0:5a29fd060ac8 532
ashleymills 0:5a29fd060ac8 533 /**
ashleymills 0:5a29fd060ac8 534 * Read the signature type of the certificate. We only support RSA-MD5 and
ashleymills 0:5a29fd060ac8 535 * RSA-SHA1 signature types.
ashleymills 0:5a29fd060ac8 536 */
ashleymills 0:5a29fd060ac8 537 int asn1_signature_type(const uint8_t *cert,
ashleymills 0:5a29fd060ac8 538 int *offset, X509_CTX *x509_ctx)
ashleymills 0:5a29fd060ac8 539 {
ashleymills 0:5a29fd060ac8 540 int ret = X509_NOT_OK, len;
ashleymills 0:5a29fd060ac8 541
ashleymills 0:5a29fd060ac8 542 if (cert[(*offset)++] != ASN1_OID)
ashleymills 0:5a29fd060ac8 543 goto end_check_sig;
ashleymills 0:5a29fd060ac8 544
ashleymills 0:5a29fd060ac8 545 len = get_asn1_length(cert, offset);
ashleymills 0:5a29fd060ac8 546
ashleymills 0:5a29fd060ac8 547 if (len == 5 && memcmp(sig_sha1WithRSAEncrypt, &cert[*offset],
ashleymills 0:5a29fd060ac8 548 SIG_IIS6_OID_SIZE) == 0)
ashleymills 0:5a29fd060ac8 549 {
ashleymills 0:5a29fd060ac8 550 x509_ctx->sig_type = SIG_TYPE_SHA1;
ashleymills 0:5a29fd060ac8 551 }
ashleymills 0:5a29fd060ac8 552 else
ashleymills 0:5a29fd060ac8 553 {
ashleymills 0:5a29fd060ac8 554 if (memcmp(sig_oid_prefix, &cert[*offset], SIG_OID_PREFIX_SIZE))
ashleymills 0:5a29fd060ac8 555 goto end_check_sig; /* unrecognised cert type */
ashleymills 0:5a29fd060ac8 556
ashleymills 0:5a29fd060ac8 557 x509_ctx->sig_type = cert[*offset + SIG_OID_PREFIX_SIZE];
ashleymills 0:5a29fd060ac8 558 }
ashleymills 0:5a29fd060ac8 559
ashleymills 0:5a29fd060ac8 560 *offset += len;
ashleymills 0:5a29fd060ac8 561 asn1_skip_obj(cert, offset, ASN1_NULL); /* if it's there */
ashleymills 0:5a29fd060ac8 562 ret = X509_OK;
ashleymills 0:5a29fd060ac8 563
ashleymills 0:5a29fd060ac8 564 end_check_sig:
ashleymills 0:5a29fd060ac8 565 return ret;
ashleymills 0:5a29fd060ac8 566 }
ashleymills 0:5a29fd060ac8 567