[331] | 1 | /*
|
---|
| 2 | * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
|
---|
| 3 | *
|
---|
| 4 | * Licensed under the OpenSSL license (the "License"). You may not use
|
---|
| 5 | * this file except in compliance with the License. You can obtain a copy
|
---|
| 6 | * in the file LICENSE in the source distribution or at
|
---|
| 7 | * https://www.openssl.org/source/license.html
|
---|
| 8 | */
|
---|
| 9 |
|
---|
| 10 | #include <stdio.h>
|
---|
| 11 | #include <limits.h>
|
---|
| 12 | #include "internal/cryptlib.h"
|
---|
| 13 | #include <openssl/buffer.h>
|
---|
| 14 | #include <openssl/asn1.h>
|
---|
| 15 | #include <openssl/objects.h>
|
---|
| 16 | #include <openssl/bn.h>
|
---|
| 17 | #include "internal/asn1_int.h"
|
---|
| 18 | #include "asn1_locl.h"
|
---|
| 19 |
|
---|
| 20 | int i2d_ASN1_OBJECT(const ASN1_OBJECT *a, unsigned char **pp)
|
---|
| 21 | {
|
---|
| 22 | unsigned char *p;
|
---|
| 23 | int objsize;
|
---|
| 24 |
|
---|
| 25 | if ((a == NULL) || (a->data == NULL))
|
---|
| 26 | return (0);
|
---|
| 27 |
|
---|
| 28 | objsize = ASN1_object_size(0, a->length, V_ASN1_OBJECT);
|
---|
| 29 | if (pp == NULL || objsize == -1)
|
---|
| 30 | return objsize;
|
---|
| 31 |
|
---|
| 32 | p = *pp;
|
---|
| 33 | ASN1_put_object(&p, 0, a->length, V_ASN1_OBJECT, V_ASN1_UNIVERSAL);
|
---|
| 34 | memcpy(p, a->data, a->length);
|
---|
| 35 | p += a->length;
|
---|
| 36 |
|
---|
| 37 | *pp = p;
|
---|
| 38 | return (objsize);
|
---|
| 39 | }
|
---|
| 40 |
|
---|
| 41 | int a2d_ASN1_OBJECT(unsigned char *out, int olen, const char *buf, int num)
|
---|
| 42 | {
|
---|
| 43 | int i, first, len = 0, c, use_bn;
|
---|
| 44 | char ftmp[24], *tmp = ftmp;
|
---|
| 45 | int tmpsize = sizeof ftmp;
|
---|
| 46 | const char *p;
|
---|
| 47 | unsigned long l;
|
---|
| 48 | BIGNUM *bl = NULL;
|
---|
| 49 |
|
---|
| 50 | if (num == 0)
|
---|
| 51 | return (0);
|
---|
| 52 | else if (num == -1)
|
---|
| 53 | num = strlen(buf);
|
---|
| 54 |
|
---|
| 55 | p = buf;
|
---|
| 56 | c = *(p++);
|
---|
| 57 | num--;
|
---|
| 58 | if ((c >= '0') && (c <= '2')) {
|
---|
| 59 | first = c - '0';
|
---|
| 60 | } else {
|
---|
| 61 | ASN1err(ASN1_F_A2D_ASN1_OBJECT, ASN1_R_FIRST_NUM_TOO_LARGE);
|
---|
| 62 | goto err;
|
---|
| 63 | }
|
---|
| 64 |
|
---|
| 65 | if (num <= 0) {
|
---|
| 66 | ASN1err(ASN1_F_A2D_ASN1_OBJECT, ASN1_R_MISSING_SECOND_NUMBER);
|
---|
| 67 | goto err;
|
---|
| 68 | }
|
---|
| 69 | c = *(p++);
|
---|
| 70 | num--;
|
---|
| 71 | for (;;) {
|
---|
| 72 | if (num <= 0)
|
---|
| 73 | break;
|
---|
| 74 | if ((c != '.') && (c != ' ')) {
|
---|
| 75 | ASN1err(ASN1_F_A2D_ASN1_OBJECT, ASN1_R_INVALID_SEPARATOR);
|
---|
| 76 | goto err;
|
---|
| 77 | }
|
---|
| 78 | l = 0;
|
---|
| 79 | use_bn = 0;
|
---|
| 80 | for (;;) {
|
---|
| 81 | if (num <= 0)
|
---|
| 82 | break;
|
---|
| 83 | num--;
|
---|
| 84 | c = *(p++);
|
---|
| 85 | if ((c == ' ') || (c == '.'))
|
---|
| 86 | break;
|
---|
| 87 | if ((c < '0') || (c > '9')) {
|
---|
| 88 | ASN1err(ASN1_F_A2D_ASN1_OBJECT, ASN1_R_INVALID_DIGIT);
|
---|
| 89 | goto err;
|
---|
| 90 | }
|
---|
| 91 | if (!use_bn && l >= ((ULONG_MAX - 80) / 10L)) {
|
---|
| 92 | use_bn = 1;
|
---|
| 93 | if (bl == NULL)
|
---|
| 94 | bl = BN_new();
|
---|
| 95 | if (bl == NULL || !BN_set_word(bl, l))
|
---|
| 96 | goto err;
|
---|
| 97 | }
|
---|
| 98 | if (use_bn) {
|
---|
| 99 | if (!BN_mul_word(bl, 10L)
|
---|
| 100 | || !BN_add_word(bl, c - '0'))
|
---|
| 101 | goto err;
|
---|
| 102 | } else
|
---|
| 103 | l = l * 10L + (long)(c - '0');
|
---|
| 104 | }
|
---|
| 105 | if (len == 0) {
|
---|
| 106 | if ((first < 2) && (l >= 40)) {
|
---|
| 107 | ASN1err(ASN1_F_A2D_ASN1_OBJECT,
|
---|
| 108 | ASN1_R_SECOND_NUMBER_TOO_LARGE);
|
---|
| 109 | goto err;
|
---|
| 110 | }
|
---|
| 111 | if (use_bn) {
|
---|
| 112 | if (!BN_add_word(bl, first * 40))
|
---|
| 113 | goto err;
|
---|
| 114 | } else
|
---|
| 115 | l += (long)first *40;
|
---|
| 116 | }
|
---|
| 117 | i = 0;
|
---|
| 118 | if (use_bn) {
|
---|
| 119 | int blsize;
|
---|
| 120 | blsize = BN_num_bits(bl);
|
---|
| 121 | blsize = (blsize + 6) / 7;
|
---|
| 122 | if (blsize > tmpsize) {
|
---|
| 123 | if (tmp != ftmp)
|
---|
| 124 | OPENSSL_free(tmp);
|
---|
| 125 | tmpsize = blsize + 32;
|
---|
| 126 | tmp = OPENSSL_malloc(tmpsize);
|
---|
| 127 | if (tmp == NULL)
|
---|
| 128 | goto err;
|
---|
| 129 | }
|
---|
| 130 | while (blsize--) {
|
---|
| 131 | BN_ULONG t = BN_div_word(bl, 0x80L);
|
---|
| 132 | if (t == (BN_ULONG)-1)
|
---|
| 133 | goto err;
|
---|
| 134 | tmp[i++] = (unsigned char)t;
|
---|
| 135 | }
|
---|
| 136 | } else {
|
---|
| 137 |
|
---|
| 138 | for (;;) {
|
---|
| 139 | tmp[i++] = (unsigned char)l & 0x7f;
|
---|
| 140 | l >>= 7L;
|
---|
| 141 | if (l == 0L)
|
---|
| 142 | break;
|
---|
| 143 | }
|
---|
| 144 |
|
---|
| 145 | }
|
---|
| 146 | if (out != NULL) {
|
---|
| 147 | if (len + i > olen) {
|
---|
| 148 | ASN1err(ASN1_F_A2D_ASN1_OBJECT, ASN1_R_BUFFER_TOO_SMALL);
|
---|
| 149 | goto err;
|
---|
| 150 | }
|
---|
| 151 | while (--i > 0)
|
---|
| 152 | out[len++] = tmp[i] | 0x80;
|
---|
| 153 | out[len++] = tmp[0];
|
---|
| 154 | } else
|
---|
| 155 | len += i;
|
---|
| 156 | }
|
---|
| 157 | if (tmp != ftmp)
|
---|
| 158 | OPENSSL_free(tmp);
|
---|
| 159 | BN_free(bl);
|
---|
| 160 | return (len);
|
---|
| 161 | err:
|
---|
| 162 | if (tmp != ftmp)
|
---|
| 163 | OPENSSL_free(tmp);
|
---|
| 164 | BN_free(bl);
|
---|
| 165 | return (0);
|
---|
| 166 | }
|
---|
| 167 |
|
---|
| 168 | int i2t_ASN1_OBJECT(char *buf, int buf_len, const ASN1_OBJECT *a)
|
---|
| 169 | {
|
---|
| 170 | return OBJ_obj2txt(buf, buf_len, a, 0);
|
---|
| 171 | }
|
---|
| 172 |
|
---|
| 173 | int i2a_ASN1_OBJECT(BIO *bp, const ASN1_OBJECT *a)
|
---|
| 174 | {
|
---|
| 175 | char buf[80], *p = buf;
|
---|
| 176 | int i;
|
---|
| 177 |
|
---|
| 178 | if ((a == NULL) || (a->data == NULL))
|
---|
| 179 | return (BIO_write(bp, "NULL", 4));
|
---|
| 180 | i = i2t_ASN1_OBJECT(buf, sizeof buf, a);
|
---|
| 181 | if (i > (int)(sizeof(buf) - 1)) {
|
---|
| 182 | p = OPENSSL_malloc(i + 1);
|
---|
| 183 | if (p == NULL)
|
---|
| 184 | return -1;
|
---|
| 185 | i2t_ASN1_OBJECT(p, i + 1, a);
|
---|
| 186 | }
|
---|
| 187 | if (i <= 0) {
|
---|
| 188 | i = BIO_write(bp, "<INVALID>", 9);
|
---|
| 189 | i += BIO_dump(bp, (const char *)a->data, a->length);
|
---|
| 190 | return i;
|
---|
| 191 | }
|
---|
| 192 | BIO_write(bp, p, i);
|
---|
| 193 | if (p != buf)
|
---|
| 194 | OPENSSL_free(p);
|
---|
| 195 | return (i);
|
---|
| 196 | }
|
---|
| 197 |
|
---|
| 198 | ASN1_OBJECT *d2i_ASN1_OBJECT(ASN1_OBJECT **a, const unsigned char **pp,
|
---|
| 199 | long length)
|
---|
| 200 | {
|
---|
| 201 | const unsigned char *p;
|
---|
| 202 | long len;
|
---|
| 203 | int tag, xclass;
|
---|
| 204 | int inf, i;
|
---|
| 205 | ASN1_OBJECT *ret = NULL;
|
---|
| 206 | p = *pp;
|
---|
| 207 | inf = ASN1_get_object(&p, &len, &tag, &xclass, length);
|
---|
| 208 | if (inf & 0x80) {
|
---|
| 209 | i = ASN1_R_BAD_OBJECT_HEADER;
|
---|
| 210 | goto err;
|
---|
| 211 | }
|
---|
| 212 |
|
---|
| 213 | if (tag != V_ASN1_OBJECT) {
|
---|
| 214 | i = ASN1_R_EXPECTING_AN_OBJECT;
|
---|
| 215 | goto err;
|
---|
| 216 | }
|
---|
| 217 | ret = c2i_ASN1_OBJECT(a, &p, len);
|
---|
| 218 | if (ret)
|
---|
| 219 | *pp = p;
|
---|
| 220 | return ret;
|
---|
| 221 | err:
|
---|
| 222 | ASN1err(ASN1_F_D2I_ASN1_OBJECT, i);
|
---|
| 223 | return (NULL);
|
---|
| 224 | }
|
---|
| 225 |
|
---|
| 226 | ASN1_OBJECT *c2i_ASN1_OBJECT(ASN1_OBJECT **a, const unsigned char **pp,
|
---|
| 227 | long len)
|
---|
| 228 | {
|
---|
| 229 | ASN1_OBJECT *ret = NULL, tobj;
|
---|
| 230 | const unsigned char *p;
|
---|
| 231 | unsigned char *data;
|
---|
| 232 | int i, length;
|
---|
| 233 |
|
---|
| 234 | /*
|
---|
| 235 | * Sanity check OID encoding. Need at least one content octet. MSB must
|
---|
| 236 | * be clear in the last octet. can't have leading 0x80 in subidentifiers,
|
---|
| 237 | * see: X.690 8.19.2
|
---|
| 238 | */
|
---|
| 239 | if (len <= 0 || len > INT_MAX || pp == NULL || (p = *pp) == NULL ||
|
---|
| 240 | p[len - 1] & 0x80) {
|
---|
| 241 | ASN1err(ASN1_F_C2I_ASN1_OBJECT, ASN1_R_INVALID_OBJECT_ENCODING);
|
---|
| 242 | return NULL;
|
---|
| 243 | }
|
---|
| 244 | /* Now 0 < len <= INT_MAX, so the cast is safe. */
|
---|
| 245 | length = (int)len;
|
---|
| 246 | /*
|
---|
| 247 | * Try to lookup OID in table: these are all valid encodings so if we get
|
---|
| 248 | * a match we know the OID is valid.
|
---|
| 249 | */
|
---|
| 250 | tobj.nid = NID_undef;
|
---|
| 251 | tobj.data = p;
|
---|
| 252 | tobj.length = length;
|
---|
| 253 | tobj.flags = 0;
|
---|
| 254 | i = OBJ_obj2nid(&tobj);
|
---|
| 255 | if (i != NID_undef) {
|
---|
| 256 | /*
|
---|
| 257 | * Return shared registered OID object: this improves efficiency
|
---|
| 258 | * because we don't have to return a dynamically allocated OID
|
---|
| 259 | * and NID lookups can use the cached value.
|
---|
| 260 | */
|
---|
| 261 | ret = OBJ_nid2obj(i);
|
---|
| 262 | if (a) {
|
---|
| 263 | ASN1_OBJECT_free(*a);
|
---|
| 264 | *a = ret;
|
---|
| 265 | }
|
---|
| 266 | *pp += len;
|
---|
| 267 | return ret;
|
---|
| 268 | }
|
---|
| 269 | for (i = 0; i < length; i++, p++) {
|
---|
| 270 | if (*p == 0x80 && (!i || !(p[-1] & 0x80))) {
|
---|
| 271 | ASN1err(ASN1_F_C2I_ASN1_OBJECT, ASN1_R_INVALID_OBJECT_ENCODING);
|
---|
| 272 | return NULL;
|
---|
| 273 | }
|
---|
| 274 | }
|
---|
| 275 |
|
---|
| 276 | /*
|
---|
| 277 | * only the ASN1_OBJECTs from the 'table' will have values for ->sn or
|
---|
| 278 | * ->ln
|
---|
| 279 | */
|
---|
| 280 | if ((a == NULL) || ((*a) == NULL) ||
|
---|
| 281 | !((*a)->flags & ASN1_OBJECT_FLAG_DYNAMIC)) {
|
---|
| 282 | if ((ret = ASN1_OBJECT_new()) == NULL)
|
---|
| 283 | return (NULL);
|
---|
| 284 | } else
|
---|
| 285 | ret = (*a);
|
---|
| 286 |
|
---|
| 287 | p = *pp;
|
---|
| 288 | /* detach data from object */
|
---|
| 289 | data = (unsigned char *)ret->data;
|
---|
| 290 | ret->data = NULL;
|
---|
| 291 | /* once detached we can change it */
|
---|
| 292 | if ((data == NULL) || (ret->length < length)) {
|
---|
| 293 | ret->length = 0;
|
---|
| 294 | OPENSSL_free(data);
|
---|
| 295 | data = OPENSSL_malloc(length);
|
---|
| 296 | if (data == NULL) {
|
---|
| 297 | i = ERR_R_MALLOC_FAILURE;
|
---|
| 298 | goto err;
|
---|
| 299 | }
|
---|
| 300 | ret->flags |= ASN1_OBJECT_FLAG_DYNAMIC_DATA;
|
---|
| 301 | }
|
---|
| 302 | memcpy(data, p, length);
|
---|
| 303 | /* reattach data to object, after which it remains const */
|
---|
| 304 | ret->data = data;
|
---|
| 305 | ret->length = length;
|
---|
| 306 | ret->sn = NULL;
|
---|
| 307 | ret->ln = NULL;
|
---|
| 308 | /* ret->flags=ASN1_OBJECT_FLAG_DYNAMIC; we know it is dynamic */
|
---|
| 309 | p += length;
|
---|
| 310 |
|
---|
| 311 | if (a != NULL)
|
---|
| 312 | (*a) = ret;
|
---|
| 313 | *pp = p;
|
---|
| 314 | return (ret);
|
---|
| 315 | err:
|
---|
| 316 | ASN1err(ASN1_F_C2I_ASN1_OBJECT, i);
|
---|
| 317 | if ((a == NULL) || (*a != ret))
|
---|
| 318 | ASN1_OBJECT_free(ret);
|
---|
| 319 | return (NULL);
|
---|
| 320 | }
|
---|
| 321 |
|
---|
| 322 | ASN1_OBJECT *ASN1_OBJECT_new(void)
|
---|
| 323 | {
|
---|
| 324 | ASN1_OBJECT *ret;
|
---|
| 325 |
|
---|
| 326 | ret = OPENSSL_zalloc(sizeof(*ret));
|
---|
| 327 | if (ret == NULL) {
|
---|
| 328 | ASN1err(ASN1_F_ASN1_OBJECT_NEW, ERR_R_MALLOC_FAILURE);
|
---|
| 329 | return (NULL);
|
---|
| 330 | }
|
---|
| 331 | ret->flags = ASN1_OBJECT_FLAG_DYNAMIC;
|
---|
| 332 | return (ret);
|
---|
| 333 | }
|
---|
| 334 |
|
---|
| 335 | void ASN1_OBJECT_free(ASN1_OBJECT *a)
|
---|
| 336 | {
|
---|
| 337 | if (a == NULL)
|
---|
| 338 | return;
|
---|
| 339 | if (a->flags & ASN1_OBJECT_FLAG_DYNAMIC_STRINGS) {
|
---|
| 340 | #ifndef CONST_STRICT /* disable purely for compile-time strict
|
---|
| 341 | * const checking. Doing this on a "real"
|
---|
| 342 | * compile will cause memory leaks */
|
---|
| 343 | OPENSSL_free((void*)a->sn);
|
---|
| 344 | OPENSSL_free((void*)a->ln);
|
---|
| 345 | #endif
|
---|
| 346 | a->sn = a->ln = NULL;
|
---|
| 347 | }
|
---|
| 348 | if (a->flags & ASN1_OBJECT_FLAG_DYNAMIC_DATA) {
|
---|
| 349 | OPENSSL_free((void*)a->data);
|
---|
| 350 | a->data = NULL;
|
---|
| 351 | a->length = 0;
|
---|
| 352 | }
|
---|
| 353 | if (a->flags & ASN1_OBJECT_FLAG_DYNAMIC)
|
---|
| 354 | OPENSSL_free(a);
|
---|
| 355 | }
|
---|
| 356 |
|
---|
| 357 | ASN1_OBJECT *ASN1_OBJECT_create(int nid, unsigned char *data, int len,
|
---|
| 358 | const char *sn, const char *ln)
|
---|
| 359 | {
|
---|
| 360 | ASN1_OBJECT o;
|
---|
| 361 |
|
---|
| 362 | o.sn = sn;
|
---|
| 363 | o.ln = ln;
|
---|
| 364 | o.data = data;
|
---|
| 365 | o.nid = nid;
|
---|
| 366 | o.length = len;
|
---|
| 367 | o.flags = ASN1_OBJECT_FLAG_DYNAMIC | ASN1_OBJECT_FLAG_DYNAMIC_STRINGS |
|
---|
| 368 | ASN1_OBJECT_FLAG_DYNAMIC_DATA;
|
---|
| 369 | return (OBJ_dup(&o));
|
---|
| 370 | }
|
---|