1 /* $OpenBSD: a_object.c,v 1.33 2021/12/03 16:58:11 jsing Exp $ */ 2 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 3 * All rights reserved. 4 * 5 * This package is an SSL implementation written 6 * by Eric Young (eay@cryptsoft.com). 7 * The implementation was written so as to conform with Netscapes SSL. 8 * 9 * This library is free for commercial and non-commercial use as long as 10 * the following conditions are aheared to. The following conditions 11 * apply to all code found in this distribution, be it the RC4, RSA, 12 * lhash, DES, etc., code; not just the SSL code. The SSL documentation 13 * included with this distribution is covered by the same copyright terms 14 * except that the holder is Tim Hudson (tjh@cryptsoft.com). 15 * 16 * Copyright remains Eric Young's, and as such any Copyright notices in 17 * the code are not to be removed. 18 * If this package is used in a product, Eric Young should be given attribution 19 * as the author of the parts of the library used. 20 * This can be in the form of a textual message at program startup or 21 * in documentation (online or textual) provided with the package. 22 * 23 * Redistribution and use in source and binary forms, with or without 24 * modification, are permitted provided that the following conditions 25 * are met: 26 * 1. Redistributions of source code must retain the copyright 27 * notice, this list of conditions and the following disclaimer. 28 * 2. Redistributions in binary form must reproduce the above copyright 29 * notice, this list of conditions and the following disclaimer in the 30 * documentation and/or other materials provided with the distribution. 31 * 3. All advertising materials mentioning features or use of this software 32 * must display the following acknowledgement: 33 * "This product includes cryptographic software written by 34 * Eric Young (eay@cryptsoft.com)" 35 * The word 'cryptographic' can be left out if the rouines from the library 36 * being used are not cryptographic related :-). 37 * 4. If you include any Windows specific code (or a derivative thereof) from 38 * the apps directory (application code) you must include an acknowledgement: 39 * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" 40 * 41 * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND 42 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 43 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 44 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 45 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 46 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 47 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 48 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 49 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 50 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 51 * SUCH DAMAGE. 52 * 53 * The licence and distribution terms for any publically available version or 54 * derivative of this code cannot be changed. i.e. this code cannot simply be 55 * copied and put under another distribution licence 56 * [including the GNU Public Licence.] 57 */ 58 59 #include <limits.h> 60 #include <stdio.h> 61 #include <string.h> 62 63 #include <openssl/asn1.h> 64 #include <openssl/bn.h> 65 #include <openssl/err.h> 66 #include <openssl/buffer.h> 67 #include <openssl/objects.h> 68 69 int 70 i2d_ASN1_OBJECT(const ASN1_OBJECT *a, unsigned char **pp) 71 { 72 unsigned char *p; 73 int objsize; 74 75 if ((a == NULL) || (a->data == NULL)) 76 return (0); 77 78 objsize = ASN1_object_size(0, a->length, V_ASN1_OBJECT); 79 if (pp == NULL) 80 return objsize; 81 82 p = *pp; 83 ASN1_put_object(&p, 0, a->length, V_ASN1_OBJECT, V_ASN1_UNIVERSAL); 84 memcpy(p, a->data, a->length); 85 p += a->length; 86 87 *pp = p; 88 return (objsize); 89 } 90 91 int 92 a2d_ASN1_OBJECT(unsigned char *out, int olen, const char *buf, int num) 93 { 94 int i, first, len = 0, c, use_bn; 95 char ftmp[24], *tmp = ftmp; 96 int tmpsize = sizeof ftmp; 97 const char *p; 98 unsigned long l; 99 BIGNUM *bl = NULL; 100 101 if (num == 0) 102 return (0); 103 else if (num == -1) 104 num = strlen(buf); 105 106 p = buf; 107 c = *(p++); 108 num--; 109 if ((c >= '0') && (c <= '2')) { 110 first= c-'0'; 111 } else { 112 ASN1error(ASN1_R_FIRST_NUM_TOO_LARGE); 113 goto err; 114 } 115 116 if (num <= 0) { 117 ASN1error(ASN1_R_MISSING_SECOND_NUMBER); 118 goto err; 119 } 120 c = *(p++); 121 num--; 122 for (;;) { 123 if (num <= 0) 124 break; 125 if ((c != '.') && (c != ' ')) { 126 ASN1error(ASN1_R_INVALID_SEPARATOR); 127 goto err; 128 } 129 l = 0; 130 use_bn = 0; 131 for (;;) { 132 if (num <= 0) 133 break; 134 num--; 135 c = *(p++); 136 if ((c == ' ') || (c == '.')) 137 break; 138 if ((c < '0') || (c > '9')) { 139 ASN1error(ASN1_R_INVALID_DIGIT); 140 goto err; 141 } 142 if (!use_bn && l >= ((ULONG_MAX - 80) / 10L)) { 143 use_bn = 1; 144 if (!bl) 145 bl = BN_new(); 146 if (!bl || !BN_set_word(bl, l)) 147 goto err; 148 } 149 if (use_bn) { 150 if (!BN_mul_word(bl, 10L) || 151 !BN_add_word(bl, c-'0')) 152 goto err; 153 } else 154 l = l * 10L + (long)(c - '0'); 155 } 156 if (len == 0) { 157 if ((first < 2) && (l >= 40)) { 158 ASN1error(ASN1_R_SECOND_NUMBER_TOO_LARGE); 159 goto err; 160 } 161 if (use_bn) { 162 if (!BN_add_word(bl, first * 40)) 163 goto err; 164 } else 165 l += (long)first * 40; 166 } 167 i = 0; 168 if (use_bn) { 169 int blsize; 170 blsize = BN_num_bits(bl); 171 blsize = (blsize + 6) / 7; 172 if (blsize > tmpsize) { 173 if (tmp != ftmp) 174 free(tmp); 175 tmpsize = blsize + 32; 176 tmp = malloc(tmpsize); 177 if (!tmp) 178 goto err; 179 } 180 while (blsize--) 181 tmp[i++] = (unsigned char)BN_div_word(bl, 0x80L); 182 } else { 183 184 for (;;) { 185 tmp[i++] = (unsigned char)l & 0x7f; 186 l >>= 7L; 187 if (l == 0L) 188 break; 189 } 190 191 } 192 if (out != NULL) { 193 if (len + i > olen) { 194 ASN1error(ASN1_R_BUFFER_TOO_SMALL); 195 goto err; 196 } 197 while (--i > 0) 198 out[len++] = tmp[i]|0x80; 199 out[len++] = tmp[0]; 200 } else 201 len += i; 202 } 203 if (tmp != ftmp) 204 free(tmp); 205 BN_free(bl); 206 return (len); 207 208 err: 209 if (tmp != ftmp) 210 free(tmp); 211 BN_free(bl); 212 return (0); 213 } 214 215 int 216 i2t_ASN1_OBJECT(char *buf, int buf_len, const ASN1_OBJECT *a) 217 { 218 return OBJ_obj2txt(buf, buf_len, a, 0); 219 } 220 221 int 222 i2a_ASN1_OBJECT(BIO *bp, const ASN1_OBJECT *a) 223 { 224 char *tmp = NULL; 225 size_t tlen = 256; 226 int i = -1; 227 228 if ((a == NULL) || (a->data == NULL)) 229 return(BIO_write(bp, "NULL", 4)); 230 if ((tmp = malloc(tlen)) == NULL) 231 return -1; 232 i = i2t_ASN1_OBJECT(tmp, tlen, a); 233 if (i > (int)(tlen - 1)) { 234 freezero(tmp, tlen); 235 if ((tmp = malloc(i + 1)) == NULL) 236 return -1; 237 tlen = i + 1; 238 i = i2t_ASN1_OBJECT(tmp, tlen, a); 239 } 240 if (i <= 0) 241 i = BIO_write(bp, "<INVALID>", 9); 242 else 243 i = BIO_write(bp, tmp, i); 244 freezero(tmp, tlen); 245 return (i); 246 } 247 248 ASN1_OBJECT * 249 d2i_ASN1_OBJECT(ASN1_OBJECT **a, const unsigned char **pp, long length) 250 { 251 const unsigned char *p; 252 long len; 253 int tag, xclass; 254 int inf, i; 255 ASN1_OBJECT *ret = NULL; 256 257 p = *pp; 258 inf = ASN1_get_object(&p, &len, &tag, &xclass, length); 259 if (inf & 0x80) { 260 i = ASN1_R_BAD_OBJECT_HEADER; 261 goto err; 262 } 263 264 if (tag != V_ASN1_OBJECT) { 265 i = ASN1_R_EXPECTING_AN_OBJECT; 266 goto err; 267 } 268 ret = c2i_ASN1_OBJECT(a, &p, len); 269 if (ret) 270 *pp = p; 271 return ret; 272 273 err: 274 ASN1error(i); 275 return (NULL); 276 } 277 278 ASN1_OBJECT * 279 c2i_ASN1_OBJECT(ASN1_OBJECT **a, const unsigned char **pp, long len) 280 { 281 ASN1_OBJECT *ret; 282 const unsigned char *p; 283 unsigned char *data; 284 int i, length; 285 286 /* 287 * Sanity check OID encoding: 288 * - need at least one content octet 289 * - MSB must be clear in the last octet 290 * - can't have leading 0x80 in subidentifiers, see: X.690 8.19.2 291 */ 292 if (len <= 0 || len > INT_MAX || pp == NULL || (p = *pp) == NULL || 293 p[len - 1] & 0x80) { 294 ASN1error(ASN1_R_INVALID_OBJECT_ENCODING); 295 return (NULL); 296 } 297 298 /* Now 0 < len <= INT_MAX, so the cast is safe. */ 299 length = (int)len; 300 for (i = 0; i < length; i++, p++) { 301 if (*p == 0x80 && (!i || !(p[-1] & 0x80))) { 302 ASN1error(ASN1_R_INVALID_OBJECT_ENCODING); 303 return (NULL); 304 } 305 } 306 307 if ((a == NULL) || ((*a) == NULL) || 308 !((*a)->flags & ASN1_OBJECT_FLAG_DYNAMIC)) { 309 if ((ret = ASN1_OBJECT_new()) == NULL) 310 return (NULL); 311 } else 312 ret = *a; 313 314 p = *pp; 315 316 /* detach data from object */ 317 data = (unsigned char *)ret->data; 318 freezero(data, ret->length); 319 320 data = malloc(length); 321 if (data == NULL) { 322 ASN1error(ERR_R_MALLOC_FAILURE); 323 goto err; 324 } 325 326 memcpy(data, p, length); 327 328 /* If there are dynamic strings, free them here, and clear the flag. */ 329 if ((ret->flags & ASN1_OBJECT_FLAG_DYNAMIC_STRINGS) != 0) { 330 free((void *)ret->sn); 331 free((void *)ret->ln); 332 ret->flags &= ~ASN1_OBJECT_FLAG_DYNAMIC_STRINGS; 333 } 334 335 /* reattach data to object, after which it remains const */ 336 ret->data = data; 337 ret->length = length; 338 ret->sn = NULL; 339 ret->ln = NULL; 340 ret->flags |= ASN1_OBJECT_FLAG_DYNAMIC_DATA; 341 p += length; 342 343 if (a != NULL) 344 *a = ret; 345 *pp = p; 346 return (ret); 347 348 err: 349 if (a == NULL || ret != *a) 350 ASN1_OBJECT_free(ret); 351 return (NULL); 352 } 353 354 ASN1_OBJECT * 355 ASN1_OBJECT_new(void) 356 { 357 ASN1_OBJECT *a; 358 359 if ((a = calloc(1, sizeof(ASN1_OBJECT))) == NULL) { 360 ASN1error(ERR_R_MALLOC_FAILURE); 361 return (NULL); 362 } 363 a->flags = ASN1_OBJECT_FLAG_DYNAMIC; 364 365 return a; 366 } 367 368 void 369 ASN1_OBJECT_free(ASN1_OBJECT *a) 370 { 371 if (a == NULL) 372 return; 373 if (a->flags & ASN1_OBJECT_FLAG_DYNAMIC_STRINGS) { 374 free((void *)a->sn); 375 free((void *)a->ln); 376 a->sn = a->ln = NULL; 377 } 378 if (a->flags & ASN1_OBJECT_FLAG_DYNAMIC_DATA) { 379 freezero((void *)a->data, a->length); 380 a->data = NULL; 381 a->length = 0; 382 } 383 if (a->flags & ASN1_OBJECT_FLAG_DYNAMIC) 384 free(a); 385 } 386 387 ASN1_OBJECT * 388 ASN1_OBJECT_create(int nid, unsigned char *data, int len, 389 const char *sn, const char *ln) 390 { 391 ASN1_OBJECT o; 392 393 o.sn = sn; 394 o.ln = ln; 395 o.data = data; 396 o.nid = nid; 397 o.length = len; 398 o.flags = ASN1_OBJECT_FLAG_DYNAMIC | ASN1_OBJECT_FLAG_DYNAMIC_STRINGS | 399 ASN1_OBJECT_FLAG_DYNAMIC_DATA; 400 return (OBJ_dup(&o)); 401 } 402