static int parse_tagging(const char *vstart, int vlen, int *ptag, int *pclass) { long tag_num; char *eptr; if (!vstart) return 0; tag_num = strtoul(vstart, &eptr, 10); /* Check we haven't gone past max length: should be impossible */ if (eptr && *eptr && (eptr > vstart + vlen)) return 0; if (tag_num < 0) { ASN1error(ASN1_R_INVALID_NUMBER); return 0; } *ptag = tag_num; /* If we have non numeric characters, parse them */ if (eptr) vlen -= eptr - vstart; else vlen = 0; if (vlen) { switch (*eptr) { case 'U': *pclass = V_ASN1_UNIVERSAL; break; case 'A': *pclass = V_ASN1_APPLICATION; break; case 'P': *pclass = V_ASN1_PRIVATE; break; case 'C': *pclass = V_ASN1_CONTEXT_SPECIFIC; break; default: ASN1error(ASN1_R_INVALID_MODIFIER); ERR_asprintf_error_data("Char=%c", *eptr); return 0; break; } } else *pclass = V_ASN1_CONTEXT_SPECIFIC; return 1; }
int PKCS5_pbe_set0_algor(X509_ALGOR *algor, int alg, int iter, const unsigned char *salt, int saltlen) { PBEPARAM *pbe = NULL; ASN1_STRING *pbe_str = NULL; unsigned char *sstr; pbe = PBEPARAM_new(); if (!pbe) { ASN1error(ERR_R_MALLOC_FAILURE); goto err; } if (iter <= 0) iter = PKCS5_DEFAULT_ITER; if (!ASN1_INTEGER_set(pbe->iter, iter)) { ASN1error(ERR_R_MALLOC_FAILURE); goto err; } if (!saltlen) saltlen = PKCS5_SALT_LEN; if (!ASN1_STRING_set(pbe->salt, NULL, saltlen)) { ASN1error(ERR_R_MALLOC_FAILURE); goto err; } sstr = ASN1_STRING_data(pbe->salt); if (salt) memcpy(sstr, salt, saltlen); else arc4random_buf(sstr, saltlen); if (!ASN1_item_pack(pbe, &PBEPARAM_it, &pbe_str)) { ASN1error(ERR_R_MALLOC_FAILURE); goto err; } PBEPARAM_free(pbe); pbe = NULL; if (X509_ALGOR_set0(algor, OBJ_nid2obj(alg), V_ASN1_SEQUENCE, pbe_str)) return 1; err: if (pbe != NULL) PBEPARAM_free(pbe); ASN1_STRING_free(pbe_str); return 0; }
static ASN1_TIME * ASN1_TIME_adj_internal(ASN1_TIME *s, time_t t, int offset_day, long offset_sec, int mode) { int allocated = 0; struct tm tm; size_t len; char * p; if (gmtime_r(&t, &tm) == NULL) return (NULL); if (offset_day || offset_sec) { if (!OPENSSL_gmtime_adj(&tm, offset_day, offset_sec)) return (NULL); } switch (mode) { case V_ASN1_UTCTIME: p = utctime_string_from_tm(&tm); break; case V_ASN1_GENERALIZEDTIME: p = gentime_string_from_tm(&tm); break; case RFC5280: p = rfc5280_string_from_tm(&tm); break; default: return (NULL); } if (p == NULL) { ASN1error(ASN1_R_ILLEGAL_TIME_VALUE); return (NULL); } if (s == NULL) { if ((s = ASN1_TIME_new()) == NULL) return (NULL); allocated = 1; } len = strlen(p); switch (len) { case GENTIME_LENGTH: s->type = V_ASN1_GENERALIZEDTIME; break; case UTCTIME_LENGTH: s->type = V_ASN1_UTCTIME; break; default: if (allocated) ASN1_TIME_free(s); free(p); return (NULL); } free(s->data); s->data = p; s->length = len; return (s); }
ASN1_OBJECT * d2i_ASN1_OBJECT(ASN1_OBJECT **a, const unsigned char **pp, long length) { const unsigned char *p; long len; int tag, xclass; int inf, i; ASN1_OBJECT *ret = NULL; p = *pp; inf = ASN1_get_object(&p, &len, &tag, &xclass, length); if (inf & 0x80) { i = ASN1_R_BAD_OBJECT_HEADER; goto err; } if (tag != V_ASN1_OBJECT) { i = ASN1_R_EXPECTING_AN_OBJECT; goto err; } ret = c2i_ASN1_OBJECT(a, &p, len); if (ret) *pp = p; return ret; err: ASN1error(i); return (NULL); }
ASN1_INTEGER * d2i_ASN1_UINTEGER(ASN1_INTEGER **a, const unsigned char **pp, long length) { ASN1_INTEGER *ret = NULL; const unsigned char *p; unsigned char *s; long len; int inf, tag, xclass; int i; if ((a == NULL) || ((*a) == NULL)) { if ((ret = ASN1_INTEGER_new()) == NULL) return (NULL); } else ret = (*a); p = *pp; inf = ASN1_get_object(&p, &len, &tag, &xclass, length); if (inf & 0x80) { i = ASN1_R_BAD_OBJECT_HEADER; goto err; } if (tag != V_ASN1_INTEGER) { i = ASN1_R_EXPECTING_AN_INTEGER; goto err; } /* We must malloc stuff, even for 0 bytes otherwise it * signifies a missing NULL parameter. */ s = malloc(len + 1); if (s == NULL) { i = ERR_R_MALLOC_FAILURE; goto err; } ret->type = V_ASN1_INTEGER; if (len) { if ((*p == 0) && (len != 1)) { p++; len--; } memcpy(s, p, len); p += len; } free(ret->data); ret->data = s; ret->length = (int)len; if (a != NULL) (*a) = ret; *pp = p; return (ret); err: ASN1error(i); if (a == NULL || *a != ret) ASN1_INTEGER_free(ret); return (NULL); }
ASN1_INTEGER * BN_to_ASN1_INTEGER(const BIGNUM *bn, ASN1_INTEGER *ai) { ASN1_INTEGER *ret; int len, j; if (ai == NULL) ret = ASN1_INTEGER_new(); else ret = ai; if (ret == NULL) { ASN1error(ERR_R_NESTED_ASN1_ERROR); goto err; } if (BN_is_negative(bn)) ret->type = V_ASN1_NEG_INTEGER; else ret->type = V_ASN1_INTEGER; j = BN_num_bits(bn); len = ((j == 0) ? 0 : ((j / 8) + 1)); if (ret->length < len + 4) { unsigned char *new_data = realloc(ret->data, len + 4); if (!new_data) { ASN1error(ERR_R_MALLOC_FAILURE); goto err; } ret->data = new_data; } ret->length = BN_bn2bin(bn, ret->data); /* Correct zero case */ if (!ret->length) { ret->data[0] = 0; ret->length = 1; } return (ret); err: if (ret != ai) ASN1_INTEGER_free(ret); return (NULL); }
BIGNUM * ASN1_INTEGER_to_BN(const ASN1_INTEGER *ai, BIGNUM *bn) { BIGNUM *ret; if ((ret = BN_bin2bn(ai->data, ai->length, bn)) == NULL) ASN1error(ASN1_R_BN_LIB); else if (ai->type == V_ASN1_NEG_INTEGER) BN_set_negative(ret, 1); return (ret); }
static int bitstr_cb(const char *elem, int len, void *bitstr) { long bitnum; char *eptr; if (!elem) return 0; bitnum = strtoul(elem, &eptr, 10); if (eptr && *eptr && (eptr != elem + len)) return 0; if (bitnum < 0) { ASN1error(ASN1_R_INVALID_NUMBER); return 0; } if (!ASN1_BIT_STRING_set_bit(bitstr, bitnum, 1)) { ASN1error(ERR_R_MALLOC_FAILURE); return 0; } return 1; }
STACK_OF(OPENSSL_BLOCK) * ASN1_seq_unpack(const unsigned char *buf, int len, d2i_of_void *d2i, void (*free_func)(OPENSSL_BLOCK)) { STACK_OF(OPENSSL_BLOCK) *sk; const unsigned char *pbuf; pbuf = buf; if (!(sk = d2i_ASN1_SET(NULL, &pbuf, len, d2i, free_func, V_ASN1_SEQUENCE, V_ASN1_UNIVERSAL))) ASN1error(ASN1_R_DECODE_ERROR); return sk; }
int ASN1_STRING_TABLE_add(int nid, long minsize, long maxsize, unsigned long mask, unsigned long flags) { ASN1_STRING_TABLE *tmp; char new_nid = 0; flags &= ~STABLE_FLAGS_MALLOC; if (!stable) stable = sk_ASN1_STRING_TABLE_new(sk_table_cmp); if (!stable) { ASN1error(ERR_R_MALLOC_FAILURE); return 0; } if (!(tmp = ASN1_STRING_TABLE_get(nid))) { tmp = malloc(sizeof(ASN1_STRING_TABLE)); if (!tmp) { ASN1error(ERR_R_MALLOC_FAILURE); return 0; } tmp->flags = flags | STABLE_FLAGS_MALLOC; tmp->nid = nid; new_nid = 1; } else tmp->flags = (tmp->flags & STABLE_FLAGS_MALLOC) | flags; if (minsize != -1) tmp->minsize = minsize; if (maxsize != -1) tmp->maxsize = maxsize; tmp->mask = mask; if (new_nid) { if (sk_ASN1_STRING_TABLE_push(stable, tmp) == 0) { free(tmp); ASN1error(ERR_R_MALLOC_FAILURE); return 0; } } return 1; }
static int append_exp(tag_exp_arg *arg, int exp_tag, int exp_class, int exp_constructed, int exp_pad, int imp_ok) { tag_exp_type *exp_tmp; /* Can only have IMPLICIT if permitted */ if ((arg->imp_tag != -1) && !imp_ok) { ASN1error(ASN1_R_ILLEGAL_IMPLICIT_TAG); return 0; } if (arg->exp_count == ASN1_FLAG_EXP_MAX) { ASN1error(ASN1_R_DEPTH_EXCEEDED); return 0; } exp_tmp = &arg->exp_list[arg->exp_count++]; /* If IMPLICIT set tag to implicit value then * reset implicit tag since it has been used. */ if (arg->imp_tag != -1) { exp_tmp->exp_tag = arg->imp_tag; exp_tmp->exp_class = arg->imp_class; arg->imp_tag = -1; arg->imp_class = -1; } else { exp_tmp->exp_tag = exp_tag; exp_tmp->exp_class = exp_class; } exp_tmp->exp_constructed = exp_constructed; exp_tmp->exp_pad = exp_pad; return 1; }
X509_ALGOR * PKCS5_pbe_set(int alg, int iter, const unsigned char *salt, int saltlen) { X509_ALGOR *ret; ret = X509_ALGOR_new(); if (!ret) { ASN1error(ERR_R_MALLOC_FAILURE); return NULL; } if (PKCS5_pbe_set0_algor(ret, alg, iter, salt, saltlen)) return ret; X509_ALGOR_free(ret); return NULL; }
int i2d_EC_PUBKEY(EC_KEY *a, unsigned char **pp) { EVP_PKEY *pktmp; int ret; if (!a) return (0); if ((pktmp = EVP_PKEY_new()) == NULL) { ASN1error(ERR_R_MALLOC_FAILURE); return (0); } EVP_PKEY_set1_EC_KEY(pktmp, a); ret = i2d_PUBKEY(pktmp, pp); EVP_PKEY_free(pktmp); return (ret); }
int i2d_DSA_PUBKEY(DSA *a, unsigned char **pp) { EVP_PKEY *pktmp; int ret; if (!a) return 0; pktmp = EVP_PKEY_new(); if (!pktmp) { ASN1error(ERR_R_MALLOC_FAILURE); return 0; } EVP_PKEY_set1_DSA(pktmp, a); ret = i2d_PUBKEY(pktmp, pp); EVP_PKEY_free(pktmp); return ret; }
ASN1_OBJECT * ASN1_OBJECT_new(void) { ASN1_OBJECT *ret; ret = malloc(sizeof(ASN1_OBJECT)); if (ret == NULL) { ASN1error(ERR_R_MALLOC_FAILURE); return (NULL); } ret->length = 0; ret->data = NULL; ret->nid = 0; ret->sn = NULL; ret->ln = NULL; ret->flags = ASN1_OBJECT_FLAG_DYNAMIC; return (ret); }
int ASN1_template_new(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt) { const ASN1_ITEM *it = tt->item; int ret; if (tt->flags & ASN1_TFLG_OPTIONAL) { asn1_template_clear(pval, tt); return 1; } /* If ANY DEFINED BY nothing to do */ if (tt->flags & ASN1_TFLG_ADB_MASK) { *pval = NULL; return 1; } #ifdef CRYPTO_MDEBUG if (tt->field_name) CRYPTO_push_info(tt->field_name); #endif /* If SET OF or SEQUENCE OF, its a STACK */ if (tt->flags & ASN1_TFLG_SK_MASK) { STACK_OF(ASN1_VALUE) *skval; skval = sk_ASN1_VALUE_new_null(); if (!skval) { ASN1error(ERR_R_MALLOC_FAILURE); ret = 0; goto done; } *pval = (ASN1_VALUE *)skval; ret = 1; goto done; } /* Otherwise pass it back to the item routine */ ret = asn1_item_ex_combine_new(pval, it, tt->flags & ASN1_TFLG_COMBINE); done: #ifdef CRYPTO_MDEBUG if (it->sname) CRYPTO_pop_info(); #endif return ret; }
int ASN1_INTEGER_set(ASN1_INTEGER *a, long v) { int j, k; unsigned int i; unsigned char buf[sizeof(long) + 1]; long d; a->type = V_ASN1_INTEGER; /* XXX ssl/ssl_asn1.c:i2d_SSL_SESSION() depends upon this bound vae */ if (a->length < (int)(sizeof(long) + 1)) { free(a->data); a->data = calloc(1, sizeof(long) + 1); } if (a->data == NULL) { ASN1error(ERR_R_MALLOC_FAILURE); return (0); } d = v; if (d < 0) { d = -d; a->type = V_ASN1_NEG_INTEGER; } for (i = 0; i < sizeof(long); i++) { if (d == 0) break; buf[i] = (int)d & 0xff; d >>= 8; } j = 0; for (k = i - 1; k >= 0; k--) a->data[j++] = buf[k]; a->length = j; return (1); }
static ASN1_TYPE * asn1_str2type(const char *str, int format, int utype) { ASN1_TYPE *atmp = NULL; CONF_VALUE vtmp; unsigned char *rdata; long rdlen; int no_unused = 1; if (!(atmp = ASN1_TYPE_new())) { ASN1error(ERR_R_MALLOC_FAILURE); return NULL; } if (!str) str = ""; switch (utype) { case V_ASN1_NULL: if (str && *str) { ASN1error(ASN1_R_ILLEGAL_NULL_VALUE); goto bad_form; } break; case V_ASN1_BOOLEAN: if (format != ASN1_GEN_FORMAT_ASCII) { ASN1error(ASN1_R_NOT_ASCII_FORMAT); goto bad_form; } vtmp.name = NULL; vtmp.section = NULL; vtmp.value = (char *)str; if (!X509V3_get_value_bool(&vtmp, &atmp->value.boolean)) { ASN1error(ASN1_R_ILLEGAL_BOOLEAN); goto bad_str; } break; case V_ASN1_INTEGER: case V_ASN1_ENUMERATED: if (format != ASN1_GEN_FORMAT_ASCII) { ASN1error(ASN1_R_INTEGER_NOT_ASCII_FORMAT); goto bad_form; } if (!(atmp->value.integer = s2i_ASN1_INTEGER(NULL, (char *)str))) { ASN1error(ASN1_R_ILLEGAL_INTEGER); goto bad_str; } break; case V_ASN1_OBJECT: if (format != ASN1_GEN_FORMAT_ASCII) { ASN1error(ASN1_R_OBJECT_NOT_ASCII_FORMAT); goto bad_form; } if (!(atmp->value.object = OBJ_txt2obj(str, 0))) { ASN1error(ASN1_R_ILLEGAL_OBJECT); goto bad_str; } break; case V_ASN1_UTCTIME: case V_ASN1_GENERALIZEDTIME: if (format != ASN1_GEN_FORMAT_ASCII) { ASN1error(ASN1_R_TIME_NOT_ASCII_FORMAT); goto bad_form; } if (!(atmp->value.asn1_string = ASN1_STRING_new())) { ASN1error(ERR_R_MALLOC_FAILURE); goto bad_str; } if (!ASN1_STRING_set(atmp->value.asn1_string, str, -1)) { ASN1error(ERR_R_MALLOC_FAILURE); goto bad_str; } atmp->value.asn1_string->type = utype; if (!ASN1_TIME_check(atmp->value.asn1_string)) { ASN1error(ASN1_R_ILLEGAL_TIME_VALUE); goto bad_str; } break; case V_ASN1_BMPSTRING: case V_ASN1_PRINTABLESTRING: case V_ASN1_IA5STRING: case V_ASN1_T61STRING: case V_ASN1_UTF8STRING: case V_ASN1_VISIBLESTRING: case V_ASN1_UNIVERSALSTRING: case V_ASN1_GENERALSTRING: case V_ASN1_NUMERICSTRING: if (format == ASN1_GEN_FORMAT_ASCII) format = MBSTRING_ASC; else if (format == ASN1_GEN_FORMAT_UTF8) format = MBSTRING_UTF8; else { ASN1error(ASN1_R_ILLEGAL_FORMAT); goto bad_form; } if (ASN1_mbstring_copy(&atmp->value.asn1_string, (unsigned char *)str, -1, format, ASN1_tag2bit(utype)) <= 0) { ASN1error(ERR_R_MALLOC_FAILURE); goto bad_str; } break; case V_ASN1_BIT_STRING: case V_ASN1_OCTET_STRING: if (!(atmp->value.asn1_string = ASN1_STRING_new())) { ASN1error(ERR_R_MALLOC_FAILURE); goto bad_form; } if (format == ASN1_GEN_FORMAT_HEX) { if (!(rdata = string_to_hex((char *)str, &rdlen))) { ASN1error(ASN1_R_ILLEGAL_HEX); goto bad_str; } atmp->value.asn1_string->data = rdata; atmp->value.asn1_string->length = rdlen; atmp->value.asn1_string->type = utype; } else if (format == ASN1_GEN_FORMAT_ASCII) { if (ASN1_STRING_set(atmp->value.asn1_string, str, -1) == 0) { ASN1error(ERR_R_MALLOC_FAILURE); goto bad_str; } } else if ((format == ASN1_GEN_FORMAT_BITLIST) && (utype == V_ASN1_BIT_STRING)) { if (!CONF_parse_list(str, ',', 1, bitstr_cb, atmp->value.bit_string)) { ASN1error(ASN1_R_LIST_ERROR); goto bad_str; } no_unused = 0; } else { ASN1error(ASN1_R_ILLEGAL_BITSTRING_FORMAT); goto bad_form; } if ((utype == V_ASN1_BIT_STRING) && no_unused) { atmp->value.asn1_string->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07); atmp->value.asn1_string->flags |= ASN1_STRING_FLAG_BITS_LEFT; } break; default: ASN1error(ASN1_R_UNSUPPORTED_TYPE); goto bad_str; break; } atmp->type = utype; return atmp; bad_str: ERR_asprintf_error_data("string=%s", str); bad_form: ASN1_TYPE_free(atmp); return NULL; }
int ASN1_mbstring_ncopy(ASN1_STRING **out, const unsigned char *in, int len, int inform, unsigned long mask, long minsize, long maxsize) { int str_type; int ret; char free_out; int outform, outlen = 0; ASN1_STRING *dest; unsigned char *p; int nchar; int (*cpyfunc)(unsigned long, void *) = NULL; if (len < 0) len = strlen((const char *)in); if (!mask) mask = DIRSTRING_TYPE; /* First do a string check and work out the number of characters */ switch (inform) { case MBSTRING_BMP: if (len & 1) { ASN1error(ASN1_R_INVALID_BMPSTRING_LENGTH); return -1; } nchar = len >> 1; break; case MBSTRING_UNIV: if (len & 3) { ASN1error(ASN1_R_INVALID_UNIVERSALSTRING_LENGTH); return -1; } nchar = len >> 2; break; case MBSTRING_UTF8: nchar = 0; /* This counts the characters and does utf8 syntax checking */ ret = traverse_string(in, len, MBSTRING_UTF8, in_utf8, &nchar); if (ret < 0) { ASN1error(ASN1_R_INVALID_UTF8STRING); return -1; } break; case MBSTRING_ASC: nchar = len; break; default: ASN1error(ASN1_R_UNKNOWN_FORMAT); return -1; } if ((minsize > 0) && (nchar < minsize)) { ASN1error(ASN1_R_STRING_TOO_SHORT); ERR_asprintf_error_data("minsize=%ld", minsize); return -1; } if ((maxsize > 0) && (nchar > maxsize)) { ASN1error(ASN1_R_STRING_TOO_LONG); ERR_asprintf_error_data("maxsize=%ld", maxsize); return -1; } /* Now work out minimal type (if any) */ if (traverse_string(in, len, inform, type_str, &mask) < 0) { ASN1error(ASN1_R_ILLEGAL_CHARACTERS); return -1; } /* Now work out output format and string type */ outform = MBSTRING_ASC; if (mask & B_ASN1_PRINTABLESTRING) str_type = V_ASN1_PRINTABLESTRING; else if (mask & B_ASN1_IA5STRING) str_type = V_ASN1_IA5STRING; else if (mask & B_ASN1_T61STRING) str_type = V_ASN1_T61STRING; else if (mask & B_ASN1_BMPSTRING) { str_type = V_ASN1_BMPSTRING; outform = MBSTRING_BMP; } else if (mask & B_ASN1_UNIVERSALSTRING) { str_type = V_ASN1_UNIVERSALSTRING; outform = MBSTRING_UNIV; } else { str_type = V_ASN1_UTF8STRING; outform = MBSTRING_UTF8; } if (!out) return str_type; if (*out) { free_out = 0; dest = *out; if (dest->data) { dest->length = 0; free(dest->data); dest->data = NULL; } dest->type = str_type; } else { free_out = 1; dest = ASN1_STRING_type_new(str_type); if (!dest) { ASN1error(ERR_R_MALLOC_FAILURE); return -1; } *out = dest; } /* If both the same type just copy across */ if (inform == outform) { if (!ASN1_STRING_set(dest, in, len)) { ASN1error(ERR_R_MALLOC_FAILURE); goto err; } return str_type; } /* Work out how much space the destination will need */ switch (outform) { case MBSTRING_ASC: outlen = nchar; cpyfunc = cpy_asc; break; case MBSTRING_BMP: outlen = nchar << 1; cpyfunc = cpy_bmp; break; case MBSTRING_UNIV: outlen = nchar << 2; cpyfunc = cpy_univ; break; case MBSTRING_UTF8: outlen = 0; if (traverse_string(in, len, inform, out_utf8, &outlen) < 0) { ASN1error(ASN1_R_ILLEGAL_CHARACTERS); goto err; } cpyfunc = cpy_utf8; break; } if (!(p = malloc(outlen + 1))) { ASN1error(ERR_R_MALLOC_FAILURE); goto err; } dest->length = outlen; dest->data = p; p[outlen] = 0; traverse_string(in, len, inform, cpyfunc, &p); return str_type; err: if (free_out) { ASN1_STRING_free(dest); *out = NULL; } return -1; }
int a2d_ASN1_OBJECT(unsigned char *out, int olen, const char *buf, int num) { int i, first, len = 0, c, use_bn; char ftmp[24], *tmp = ftmp; int tmpsize = sizeof ftmp; const char *p; unsigned long l; BIGNUM *bl = NULL; if (num == 0) return (0); else if (num == -1) num = strlen(buf); p = buf; c = *(p++); num--; if ((c >= '0') && (c <= '2')) { first= c-'0'; } else { ASN1error(ASN1_R_FIRST_NUM_TOO_LARGE); goto err; } if (num <= 0) { ASN1error(ASN1_R_MISSING_SECOND_NUMBER); goto err; } c = *(p++); num--; for (;;) { if (num <= 0) break; if ((c != '.') && (c != ' ')) { ASN1error(ASN1_R_INVALID_SEPARATOR); goto err; } l = 0; use_bn = 0; for (;;) { if (num <= 0) break; num--; c = *(p++); if ((c == ' ') || (c == '.')) break; if ((c < '0') || (c > '9')) { ASN1error(ASN1_R_INVALID_DIGIT); goto err; } if (!use_bn && l >= ((ULONG_MAX - 80) / 10L)) { use_bn = 1; if (!bl) bl = BN_new(); if (!bl || !BN_set_word(bl, l)) goto err; } if (use_bn) { if (!BN_mul_word(bl, 10L) || !BN_add_word(bl, c-'0')) goto err; } else l = l * 10L + (long)(c - '0'); } if (len == 0) { if ((first < 2) && (l >= 40)) { ASN1error(ASN1_R_SECOND_NUMBER_TOO_LARGE); goto err; } if (use_bn) { if (!BN_add_word(bl, first * 40)) goto err; } else l += (long)first * 40; } i = 0; if (use_bn) { int blsize; blsize = BN_num_bits(bl); blsize = (blsize + 6) / 7; if (blsize > tmpsize) { if (tmp != ftmp) free(tmp); tmpsize = blsize + 32; tmp = malloc(tmpsize); if (!tmp) goto err; } while (blsize--) tmp[i++] = (unsigned char)BN_div_word(bl, 0x80L); } else { for (;;) { tmp[i++] = (unsigned char)l & 0x7f; l >>= 7L; if (l == 0L) break; } } if (out != NULL) { if (len + i > olen) { ASN1error(ASN1_R_BUFFER_TOO_SMALL); goto err; } while (--i > 0) out[len++] = tmp[i]|0x80; out[len++] = tmp[0]; } else len += i; } if (tmp != ftmp) free(tmp); BN_free(bl); return (len); err: if (tmp != ftmp) free(tmp); BN_free(bl); return (0); }
ASN1_TYPE * ASN1_generate_v3(char *str, X509V3_CTX *cnf) { ASN1_TYPE *ret; tag_exp_arg asn1_tags; tag_exp_type *etmp; int i, len; unsigned char *orig_der = NULL, *new_der = NULL; const unsigned char *cpy_start; unsigned char *p; const unsigned char *cp; int cpy_len; long hdr_len = 0; int hdr_constructed = 0, hdr_tag, hdr_class; int r; asn1_tags.imp_tag = -1; asn1_tags.imp_class = -1; asn1_tags.format = ASN1_GEN_FORMAT_ASCII; asn1_tags.exp_count = 0; if (CONF_parse_list(str, ',', 1, asn1_cb, &asn1_tags) != 0) return NULL; if ((asn1_tags.utype == V_ASN1_SEQUENCE) || (asn1_tags.utype == V_ASN1_SET)) { if (!cnf) { ASN1error(ASN1_R_SEQUENCE_OR_SET_NEEDS_CONFIG); return NULL; } ret = asn1_multi(asn1_tags.utype, asn1_tags.str, cnf); } else ret = asn1_str2type(asn1_tags.str, asn1_tags.format, asn1_tags.utype); if (!ret) return NULL; /* If no tagging return base type */ if ((asn1_tags.imp_tag == -1) && (asn1_tags.exp_count == 0)) return ret; /* Generate the encoding */ cpy_len = i2d_ASN1_TYPE(ret, &orig_der); ASN1_TYPE_free(ret); ret = NULL; /* Set point to start copying for modified encoding */ cpy_start = orig_der; /* Do we need IMPLICIT tagging? */ if (asn1_tags.imp_tag != -1) { /* If IMPLICIT we will replace the underlying tag */ /* Skip existing tag+len */ r = ASN1_get_object(&cpy_start, &hdr_len, &hdr_tag, &hdr_class, cpy_len); if (r & 0x80) goto err; /* Update copy length */ cpy_len -= cpy_start - orig_der; /* For IMPLICIT tagging the length should match the * original length and constructed flag should be * consistent. */ if (r & 0x1) { /* Indefinite length constructed */ hdr_constructed = 2; hdr_len = 0; } else /* Just retain constructed flag */ hdr_constructed = r & V_ASN1_CONSTRUCTED; /* Work out new length with IMPLICIT tag: ignore constructed * because it will mess up if indefinite length */ len = ASN1_object_size(0, hdr_len, asn1_tags.imp_tag); } else len = cpy_len; /* Work out length in any EXPLICIT, starting from end */ for (i = 0, etmp = asn1_tags.exp_list + asn1_tags.exp_count - 1; i < asn1_tags.exp_count; i++, etmp--) { /* Content length: number of content octets + any padding */ len += etmp->exp_pad; etmp->exp_len = len; /* Total object length: length including new header */ len = ASN1_object_size(0, len, etmp->exp_tag); } /* Allocate buffer for new encoding */ new_der = malloc(len); if (!new_der) goto err; /* Generate tagged encoding */ p = new_der; /* Output explicit tags first */ for (i = 0, etmp = asn1_tags.exp_list; i < asn1_tags.exp_count; i++, etmp++) { ASN1_put_object(&p, etmp->exp_constructed, etmp->exp_len, etmp->exp_tag, etmp->exp_class); if (etmp->exp_pad) *p++ = 0; } /* If IMPLICIT, output tag */ if (asn1_tags.imp_tag != -1) { if (asn1_tags.imp_class == V_ASN1_UNIVERSAL && (asn1_tags.imp_tag == V_ASN1_SEQUENCE || asn1_tags.imp_tag == V_ASN1_SET)) hdr_constructed = V_ASN1_CONSTRUCTED; ASN1_put_object(&p, hdr_constructed, hdr_len, asn1_tags.imp_tag, asn1_tags.imp_class); } /* Copy across original encoding */ memcpy(p, cpy_start, cpy_len); cp = new_der; /* Obtain new ASN1_TYPE structure */ ret = d2i_ASN1_TYPE(NULL, &cp, len); err: free(orig_der); free(new_der); return ret; }
ASN1_INTEGER * c2i_ASN1_INTEGER(ASN1_INTEGER **a, const unsigned char **pp, long len) { ASN1_INTEGER *ret = NULL; const unsigned char *p, *pend; unsigned char *to, *s; int i; if ((a == NULL) || ((*a) == NULL)) { if ((ret = ASN1_INTEGER_new()) == NULL) return (NULL); } else ret = (*a); p = *pp; pend = p + len; /* We must malloc stuff, even for 0 bytes otherwise it * signifies a missing NULL parameter. */ s = malloc(len + 1); if (s == NULL) { i = ERR_R_MALLOC_FAILURE; goto err; } to = s; if (!len) { /* Strictly speaking this is an illegal INTEGER but we * tolerate it. */ ret->type = V_ASN1_INTEGER; } else if (*p & 0x80) /* a negative number */ { ret->type = V_ASN1_NEG_INTEGER; if ((*p == 0xff) && (len != 1)) { p++; len--; } i = len; p += i - 1; to += i - 1; while((!*p) && i) { *(to--) = 0; i--; p--; } /* Special case: if all zeros then the number will be of * the form FF followed by n zero bytes: this corresponds to * 1 followed by n zero bytes. We've already written n zeros * so we just append an extra one and set the first byte to * a 1. This is treated separately because it is the only case * where the number of bytes is larger than len. */ if (!i) { *s = 1; s[len] = 0; len++; } else { *(to--) = (*(p--) ^ 0xff) + 1; i--; for (; i > 0; i--) *(to--) = *(p--) ^ 0xff; } } else { ret->type = V_ASN1_INTEGER; if ((*p == 0) && (len != 1)) { p++; len--; } memcpy(s, p, len); } free(ret->data); ret->data = s; ret->length = (int)len; if (a != NULL) (*a) = ret; *pp = pend; return (ret); err: ASN1error(i); if (a == NULL || *a != ret) ASN1_INTEGER_free(ret); return (NULL); }
int ASN1_item_sign_ctx(const ASN1_ITEM *it, X509_ALGOR *algor1, X509_ALGOR *algor2, ASN1_BIT_STRING *signature, void *asn, EVP_MD_CTX *ctx) { const EVP_MD *type; EVP_PKEY *pkey; unsigned char *buf_in = NULL, *buf_out = NULL; size_t inl = 0, outl = 0, outll = 0; int signid, paramtype; int rv; type = EVP_MD_CTX_md(ctx); pkey = EVP_PKEY_CTX_get0_pkey(ctx->pctx); if (!type || !pkey) { ASN1error(ASN1_R_CONTEXT_NOT_INITIALISED); return 0; } if (pkey->ameth->item_sign) { rv = pkey->ameth->item_sign(ctx, it, asn, algor1, algor2, signature); if (rv == 1) outl = signature->length; /* Return value meanings: * <=0: error. * 1: method does everything. * 2: carry on as normal. * 3: ASN1 method sets algorithm identifiers: just sign. */ if (rv <= 0) ASN1error(ERR_R_EVP_LIB); if (rv <= 1) goto err; } else rv = 2; if (rv == 2) { if (type->flags & EVP_MD_FLAG_PKEY_METHOD_SIGNATURE) { if (!pkey->ameth || !OBJ_find_sigid_by_algs(&signid, EVP_MD_nid(type), pkey->ameth->pkey_id)) { ASN1error(ASN1_R_DIGEST_AND_KEY_TYPE_NOT_SUPPORTED); return 0; } } else signid = type->pkey_type; if (pkey->ameth->pkey_flags & ASN1_PKEY_SIGPARAM_NULL) paramtype = V_ASN1_NULL; else paramtype = V_ASN1_UNDEF; if (algor1) X509_ALGOR_set0(algor1, OBJ_nid2obj(signid), paramtype, NULL); if (algor2) X509_ALGOR_set0(algor2, OBJ_nid2obj(signid), paramtype, NULL); } inl = ASN1_item_i2d(asn, &buf_in, it); outll = outl = EVP_PKEY_size(pkey); buf_out = malloc(outl); if ((buf_in == NULL) || (buf_out == NULL)) { outl = 0; ASN1error(ERR_R_MALLOC_FAILURE); goto err; } if (!EVP_DigestSignUpdate(ctx, buf_in, inl) || !EVP_DigestSignFinal(ctx, buf_out, &outl)) { outl = 0; ASN1error(ERR_R_EVP_LIB); goto err; } free(signature->data); signature->data = buf_out; buf_out = NULL; signature->length = outl; /* In the interests of compatibility, I'll make sure that * the bit string has a 'not-used bits' value of 0 */ signature->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT|0x07); signature->flags |= ASN1_STRING_FLAG_BITS_LEFT; err: EVP_MD_CTX_cleanup(ctx); freezero((char *)buf_in, inl); freezero((char *)buf_out, outll); return (outl); }
static int asn1_cb(const char *elem, int len, void *bitstr) { tag_exp_arg *arg = bitstr; int i; int utype; int vlen = 0; const char *p, *vstart = NULL; int tmp_tag, tmp_class; for (i = 0, p = elem; i < len; p++, i++) { /* Look for the ':' in name value pairs */ if (*p == ':') { vstart = p + 1; vlen = len - (vstart - elem); len = p - elem; break; } } utype = asn1_str2tag(elem, len); if (utype == -1) { ASN1error(ASN1_R_UNKNOWN_TAG); ERR_asprintf_error_data("tag=%s", elem); return -1; } /* If this is not a modifier mark end of string and exit */ if (!(utype & ASN1_GEN_FLAG)) { arg->utype = utype; arg->str = vstart; /* If no value and not end of string, error */ if (!vstart && elem[len]) { ASN1error(ASN1_R_MISSING_VALUE); return -1; } return 0; } switch (utype) { case ASN1_GEN_FLAG_IMP: /* Check for illegal multiple IMPLICIT tagging */ if (arg->imp_tag != -1) { ASN1error(ASN1_R_ILLEGAL_NESTED_TAGGING); return -1; } if (!parse_tagging(vstart, vlen, &arg->imp_tag, &arg->imp_class)) return -1; break; case ASN1_GEN_FLAG_EXP: if (!parse_tagging(vstart, vlen, &tmp_tag, &tmp_class)) return -1; if (!append_exp(arg, tmp_tag, tmp_class, 1, 0, 0)) return -1; break; case ASN1_GEN_FLAG_SEQWRAP: if (!append_exp(arg, V_ASN1_SEQUENCE, V_ASN1_UNIVERSAL, 1, 0, 1)) return -1; break; case ASN1_GEN_FLAG_SETWRAP: if (!append_exp(arg, V_ASN1_SET, V_ASN1_UNIVERSAL, 1, 0, 1)) return -1; break; case ASN1_GEN_FLAG_BITWRAP: if (!append_exp(arg, V_ASN1_BIT_STRING, V_ASN1_UNIVERSAL, 0, 1, 1)) return -1; break; case ASN1_GEN_FLAG_OCTWRAP: if (!append_exp(arg, V_ASN1_OCTET_STRING, V_ASN1_UNIVERSAL, 0, 0, 1)) return -1; break; case ASN1_GEN_FLAG_FORMAT: if (vstart == NULL) { ASN1error(ASN1_R_ILLEGAL_FORMAT); return -1; } if (!strncmp(vstart, "ASCII", 5)) arg->format = ASN1_GEN_FORMAT_ASCII; else if (!strncmp(vstart, "UTF8", 4)) arg->format = ASN1_GEN_FORMAT_UTF8; else if (!strncmp(vstart, "HEX", 3)) arg->format = ASN1_GEN_FORMAT_HEX; else if (!strncmp(vstart, "BITLIST", 7)) arg->format = ASN1_GEN_FORMAT_BITLIST; else { ASN1error(ASN1_R_UNKOWN_FORMAT); return -1; } break; } return 1; }
static int asn1_item_ex_combine_new(ASN1_VALUE **pval, const ASN1_ITEM *it, int combine) { const ASN1_TEMPLATE *tt = NULL; const ASN1_EXTERN_FUNCS *ef; const ASN1_AUX *aux = it->funcs; ASN1_aux_cb *asn1_cb = NULL; ASN1_VALUE **pseqval; int i; if (aux != NULL && aux->asn1_cb != NULL) asn1_cb = aux->asn1_cb; if (!combine) *pval = NULL; #ifdef CRYPTO_MDEBUG if (it->sname) CRYPTO_push_info(it->sname); #endif switch (it->itype) { case ASN1_ITYPE_EXTERN: ef = it->funcs; if (ef && ef->asn1_ex_new) { if (!ef->asn1_ex_new(pval, it)) goto memerr; } break; case ASN1_ITYPE_PRIMITIVE: if (it->templates) { if (!ASN1_template_new(pval, it->templates)) goto memerr; } else if (!ASN1_primitive_new(pval, it)) goto memerr; break; case ASN1_ITYPE_MSTRING: if (!ASN1_primitive_new(pval, it)) goto memerr; break; case ASN1_ITYPE_CHOICE: if (asn1_cb) { i = asn1_cb(ASN1_OP_NEW_PRE, pval, it, NULL); if (!i) goto auxerr; if (i == 2) { #ifdef CRYPTO_MDEBUG if (it->sname) CRYPTO_pop_info(); #endif return 1; } } if (!combine) { *pval = calloc(1, it->size); if (!*pval) goto memerr; } asn1_set_choice_selector(pval, -1, it); if (asn1_cb && !asn1_cb(ASN1_OP_NEW_POST, pval, it, NULL)) goto auxerr; break; case ASN1_ITYPE_NDEF_SEQUENCE: case ASN1_ITYPE_SEQUENCE: if (asn1_cb) { i = asn1_cb(ASN1_OP_NEW_PRE, pval, it, NULL); if (!i) goto auxerr; if (i == 2) { #ifdef CRYPTO_MDEBUG if (it->sname) CRYPTO_pop_info(); #endif return 1; } } if (!combine) { *pval = calloc(1, it->size); if (!*pval) goto memerr; asn1_do_lock(pval, 0, it); asn1_enc_init(pval, it); } for (i = 0, tt = it->templates; i < it->tcount; tt++, i++) { pseqval = asn1_get_field_ptr(pval, tt); if (!ASN1_template_new(pseqval, tt)) goto memerr; } if (asn1_cb && !asn1_cb(ASN1_OP_NEW_POST, pval, it, NULL)) goto auxerr; break; } #ifdef CRYPTO_MDEBUG if (it->sname) CRYPTO_pop_info(); #endif return 1; memerr: ASN1error(ERR_R_MALLOC_FAILURE); #ifdef CRYPTO_MDEBUG if (it->sname) CRYPTO_pop_info(); #endif return 0; auxerr: ASN1error(ASN1_R_AUX_ERROR); ASN1_item_ex_free(pval, it); #ifdef CRYPTO_MDEBUG if (it->sname) CRYPTO_pop_info(); #endif return 0; }
ASN1_OBJECT * c2i_ASN1_OBJECT(ASN1_OBJECT **a, const unsigned char **pp, long len) { ASN1_OBJECT *ret; const unsigned char *p; unsigned char *data; int i, length; /* * Sanity check OID encoding: * - need at least one content octet * - MSB must be clear in the last octet * - can't have leading 0x80 in subidentifiers, see: X.690 8.19.2 */ if (len <= 0 || len > INT_MAX || pp == NULL || (p = *pp) == NULL || p[len - 1] & 0x80) { ASN1error(ASN1_R_INVALID_OBJECT_ENCODING); return (NULL); } /* Now 0 < len <= INT_MAX, so the cast is safe. */ length = (int)len; for (i = 0; i < length; i++, p++) { if (*p == 0x80 && (!i || !(p[-1] & 0x80))) { ASN1error(ASN1_R_INVALID_OBJECT_ENCODING); return (NULL); } } /* only the ASN1_OBJECTs from the 'table' will have values * for ->sn or ->ln */ if ((a == NULL) || ((*a) == NULL) || !((*a)->flags & ASN1_OBJECT_FLAG_DYNAMIC)) { if ((ret = ASN1_OBJECT_new()) == NULL) return (NULL); } else ret = *a; p = *pp; /* detach data from object */ data = (unsigned char *)ret->data; if (data != NULL) explicit_bzero(data, ret->length); free(data); data = malloc(length); if (data == NULL) { ASN1error(ERR_R_MALLOC_FAILURE); goto err; } memcpy(data, p, length); /* reattach data to object, after which it remains const */ ret->data = data; ret->length = length; ret->sn = NULL; ret->ln = NULL; ret->flags |= ASN1_OBJECT_FLAG_DYNAMIC_DATA; p += length; if (a != NULL) *a = ret; *pp = p; return (ret); err: if (a == NULL || ret != *a) ASN1_OBJECT_free(ret); return (NULL); }