Rough and ready port of axTLS
ssl/asn1.c@0:5a29fd060ac8, 2013-05-13 (annotated)
- Committer:
- ashleymills
- Date:
- Mon May 13 18:15:18 2013 +0000
- Revision:
- 0:5a29fd060ac8
initial commit
Who changed what in which revision?
User | Revision | Line number | New 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 |