/* Function: GetX509PublicKeyParameterBytes Used by System.Security.Cryptography.X509Certificates' OpenSslX509CertificateReader to copy out the parameters to the algorithm used by the certificate public key Return values: 0: Invalid X509 pointer 1: Data was copied Any negative value: The input buffer size was reported as insufficient. A buffer of size ABS(return) is required. */ int GetX509PublicKeyParameterBytes( X509* x509, unsigned char* pBuf, int cBuf) { if (!x509 || !x509->cert_info || !x509->cert_info->key || !x509->cert_info->key->algor) { return 0; } ASN1_TYPE* parameter = x509->cert_info->key->algor->parameter; int len = i2d_ASN1_TYPE(parameter, NULL); if (cBuf < len) { return -len; } unsigned char* pBuf2 = pBuf; len = i2d_ASN1_TYPE(parameter, &pBuf2); if (len > 0) { return 1; } return 0; }
static int do_dump(unsigned long lflags, char_io *io_ch, void *arg, ASN1_STRING *str) { /* * Placing the ASN1_STRING in a temp ASN1_TYPE allows the DER encoding to * readily obtained */ ASN1_TYPE t; unsigned char *der_buf, *p; int outlen, der_len; if (!io_ch(arg, "#", 1)) return -1; /* If we don't dump DER encoding just dump content octets */ if (!(lflags & ASN1_STRFLGS_DUMP_DER)) { outlen = do_hex_dump(io_ch, arg, str->data, str->length); if (outlen < 0) return -1; return outlen + 1; } t.type = str->type; t.value.ptr = (char *)str; der_len = i2d_ASN1_TYPE(&t, NULL); der_buf = OPENSSL_malloc(der_len); if (!der_buf) return -1; p = der_buf; i2d_ASN1_TYPE(&t, &p); outlen = do_hex_dump(io_ch, arg, der_buf, der_len); OPENSSL_free(der_buf); if (outlen < 0) return -1; return outlen + 1; }
static int do_generate(BIO *bio, char *genstr, char *genconf, BUF_MEM *buf) { CONF *cnf = NULL; int len; long errline; unsigned char *p; ASN1_TYPE *atyp = NULL; if (genconf) { cnf = NCONF_new(NULL); if (!NCONF_load(cnf, genconf, &errline)) goto conferr; if (!genstr) genstr = NCONF_get_string(cnf, "default", "asn1"); if (!genstr) { BIO_printf(bio, "Can't find 'asn1' in '%s'\n", genconf); goto err; } } atyp = ASN1_generate_nconf(genstr, cnf); NCONF_free(cnf); if (!atyp) return -1; len = i2d_ASN1_TYPE(atyp, NULL); if (len <= 0) goto err; if (!BUF_MEM_grow(buf,len)) goto err; p=(unsigned char *)buf->data; i2d_ASN1_TYPE(atyp, &p); ASN1_TYPE_free(atyp); return len; conferr: if (errline > 0) BIO_printf(bio, "Error on line %ld of config file '%s'\n", errline, genconf); else BIO_printf(bio, "Error loading config file '%s'\n", genconf); err: NCONF_free(cnf); ASN1_TYPE_free(atyp); return -1; }
/* sequence */ int i2d_X509_ATTRIBUTE(X509_ATTRIBUTE *a, unsigned char **pp) { int k=0; int r=0,ret=0; unsigned char **p=NULL; if (a == NULL) return(0); p=NULL; for (;;) { if (k) { r=ASN1_object_size(1,ret,V_ASN1_SEQUENCE); if (pp == NULL) return(r); p=pp; ASN1_put_object(p,1,ret,V_ASN1_SEQUENCE, V_ASN1_UNIVERSAL); } ret+=i2d_ASN1_OBJECT(a->object,p); if (a->set) ret+=i2d_ASN1_SET_OF_ASN1_TYPE(a->value.set,p,(i2d_func_t)i2d_ASN1_TYPE, V_ASN1_SET,V_ASN1_UNIVERSAL,IS_SET); else ret+=i2d_ASN1_TYPE(a->value.single,p); if (k++) return(r); } }
static int openssl_xattr_type(lua_State*L) { X509_ATTRIBUTE* attr = CHECK_OBJECT(1,X509_ATTRIBUTE, "openssl.x509_attribute"); int loc = luaL_checkint(L, 2); ASN1_TYPE *type = X509_ATTRIBUTE_get0_type(attr, loc); if(type) { int len; unsigned char*out; len = i2d_ASN1_TYPE(type,NULL); out = OPENSSL_malloc(len); len = i2d_ASN1_TYPE(type,NULL); type = d2i_ASN1_TYPE(NULL, &out, len); PUSH_OBJECT(type,"openssl.asn1_type"); return 1; }else lua_pushnil(L); return 1; }
static int do_generate(char *genstr, const char *genconf, BUF_MEM *buf) { CONF *cnf = NULL; int len; unsigned char *p; ASN1_TYPE *atyp = NULL; if (genconf) { if ((cnf = app_load_config(genconf)) == NULL) goto err; if (!genstr) genstr = NCONF_get_string(cnf, "default", "asn1"); if (!genstr) { BIO_printf(bio_err, "Can't find 'asn1' in '%s'\n", genconf); goto err; } } atyp = ASN1_generate_nconf(genstr, cnf); NCONF_free(cnf); cnf = NULL; if (!atyp) return -1; len = i2d_ASN1_TYPE(atyp, NULL); if (len <= 0) goto err; if (!BUF_MEM_grow(buf, len)) goto err; p = (unsigned char *)buf->data; i2d_ASN1_TYPE(atyp, &p); ASN1_TYPE_free(atyp); return len; err: NCONF_free(cnf); ASN1_TYPE_free(atyp); return -1; }
static int ossl_i2d_ASN1_TYPE(ASN1_TYPE *a, unsigned char **pp) { #if OPENSSL_VERSION_NUMBER < 0x00907000L if(!a) return 0; if(a->type == V_ASN1_BOOLEAN) return i2d_ASN1_BOOLEAN(a->value.boolean, pp); #endif return i2d_ASN1_TYPE(a, pp); }
static unsigned char *generic_asn1(char *value, X509V3_CTX *ctx, long *ext_len) { ASN1_TYPE *typ; unsigned char *ext_der = NULL; typ = ASN1_generate_v3(value, ctx); if (typ == NULL) return NULL; *ext_len = i2d_ASN1_TYPE(typ, &ext_der); ASN1_TYPE_free(typ); return ext_der; }
int i2d_GENERAL_NAME(GENERAL_NAME *a, unsigned char **pp) { unsigned char *p; int ret; ret = 0; /* Save the location of initial TAG */ if(pp) p = *pp; else p = NULL; /* GEN_DNAME needs special treatment because of EXPLICIT tag */ if(a->type == GEN_DIRNAME) { int v = 0; M_ASN1_I2D_len_EXP_opt(a->d.dirn, i2d_X509_NAME, 4, v); if(!p) return ret; M_ASN1_I2D_put_EXP_opt(a->d.dirn, i2d_X509_NAME, 4, v); *pp = p; return ret; } switch(a->type) { case GEN_X400: case GEN_EDIPARTY: ret = i2d_ASN1_TYPE(a->d.other, pp); break; case GEN_OTHERNAME: ret = i2d_OTHERNAME(a->d.otherName, pp); break; case GEN_EMAIL: case GEN_DNS: case GEN_URI: ret = i2d_ASN1_IA5STRING(a->d.ia5, pp); break; case GEN_IPADD: ret = i2d_ASN1_OCTET_STRING(a->d.ip, pp); break; case GEN_RID: ret = i2d_ASN1_OBJECT(a->d.rid, pp); break; } /* Replace TAG with IMPLICIT value */ if(p) *p = (*p & V_ASN1_CONSTRUCTED) | a->type; return ret; }
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; 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) { ASN1err(ASN1_F_ASN1_GENERATE_V3, 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 -= (int)(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 = OPENSSL_malloc(len); /* 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) 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: if (orig_der) OPENSSL_free(orig_der); if (new_der) OPENSSL_free(new_der); return ret; }
/* * We need to replace a standard chunk of PKCS7 signature with one mandated * by Authenticode. Problem is, replacing it just like that and then calling * PKCS7_final() would make OpenSSL segfault somewhere in PKCS7_dataFinal(). * So, instead, we call PKCS7_dataInit(), then put our Authenticode-specific * data into BIO it returned, then call PKCS7_dataFinal() - which now somehow * does not panic - and _then_ we replace it in the signature. This technique * was used in sbsigntool by Jeremy Kerr, and might have originated in * osslsigncode. */ static void magic(PKCS7 *pkcs7, const char *digest, size_t digest_len) { BIO *bio, *t_bio; ASN1_TYPE *t; ASN1_STRING *s; CONF *cnf; unsigned char *buf, *tmp; char *digest_hex, *magic_conf, *str; int len, nid, ok; digest_hex = bin2hex(digest, digest_len); /* * Construct the SpcIndirectDataContent chunk. */ nid = OBJ_create("1.3.6.1.4.1.311.2.1.4", NULL, NULL); asprintf(&magic_conf, magic_fmt, digest_hex); if (magic_conf == NULL) err(1, "asprintf"); bio = BIO_new_mem_buf((void *)magic_conf, -1); if (bio == NULL) { ERR_print_errors_fp(stderr); errx(1, "BIO_new_mem_buf(3) failed"); } cnf = NCONF_new(NULL); if (cnf == NULL) { ERR_print_errors_fp(stderr); errx(1, "NCONF_new(3) failed"); } ok = NCONF_load_bio(cnf, bio, NULL); if (ok == 0) { ERR_print_errors_fp(stderr); errx(1, "NCONF_load_bio(3) failed"); } str = NCONF_get_string(cnf, "default", "asn1"); if (str == NULL) { ERR_print_errors_fp(stderr); errx(1, "NCONF_get_string(3) failed"); } t = ASN1_generate_nconf(str, cnf); if (t == NULL) { ERR_print_errors_fp(stderr); errx(1, "ASN1_generate_nconf(3) failed"); } /* * We now have our proprietary piece of ASN.1. Let's do * the actual signing. */ len = i2d_ASN1_TYPE(t, NULL); tmp = buf = calloc(1, len); if (tmp == NULL) err(1, "calloc"); i2d_ASN1_TYPE(t, &tmp); /* * We now have contents of 't' stuffed into memory buffer 'buf'. */ tmp = NULL; t = NULL; t_bio = PKCS7_dataInit(pkcs7, NULL); if (t_bio == NULL) { ERR_print_errors_fp(stderr); errx(1, "PKCS7_dataInit(3) failed"); } BIO_write(t_bio, buf + 2, len - 2); ok = PKCS7_dataFinal(pkcs7, t_bio); if (ok == 0) { ERR_print_errors_fp(stderr); errx(1, "PKCS7_dataFinal(3) failed"); } t = ASN1_TYPE_new(); s = ASN1_STRING_new(); ASN1_STRING_set(s, buf, len); ASN1_TYPE_set(t, V_ASN1_SEQUENCE, s); PKCS7_set0_type_other(pkcs7->d.sign->contents, nid, t); }