/* Decodes the PKCS #7 signed data, and returns an ASN1_TYPE, * which holds them. If raw is non null then the raw decoded * data are copied (they are locally allocated) there. */ static int _decode_pkcs7_signed_data (ASN1_TYPE pkcs7, ASN1_TYPE * sdata, gnutls_datum_t * raw) { char oid[MAX_OID_SIZE]; ASN1_TYPE c2; opaque *tmp = NULL; int tmp_size, len, result; len = sizeof (oid) - 1; result = asn1_read_value (pkcs7, "contentType", oid, &len); if (result != ASN1_SUCCESS) { gnutls_assert (); return _gnutls_asn2err (result); } if (strcmp (oid, SIGNED_DATA_OID) != 0) { gnutls_assert (); _gnutls_x509_log ("Unknown PKCS7 Content OID '%s'\n", oid); return GNUTLS_E_UNKNOWN_PKCS_CONTENT_TYPE; } if ((result = asn1_create_element (_gnutls_get_pkix (), "PKIX1.pkcs-7-SignedData", &c2)) != ASN1_SUCCESS) { gnutls_assert (); return _gnutls_asn2err (result); } /* the Signed-data has been created, so * decode them. */ tmp_size = 0; result = asn1_read_value (pkcs7, "content", NULL, &tmp_size); if (result != ASN1_MEM_ERROR) { gnutls_assert (); result = _gnutls_asn2err (result); goto cleanup; } tmp = gnutls_malloc (tmp_size); if (tmp == NULL) { gnutls_assert (); result = GNUTLS_E_MEMORY_ERROR; goto cleanup; } result = asn1_read_value (pkcs7, "content", tmp, &tmp_size); if (result != ASN1_SUCCESS) { gnutls_assert (); result = _gnutls_asn2err (result); goto cleanup; } /* tmp, tmp_size hold the data and the size of the CertificateSet structure * actually the ANY stuff. */ /* Step 1. In case of a signed structure extract certificate set. */ result = asn1_der_decoding (&c2, tmp, tmp_size, NULL); if (result != ASN1_SUCCESS) { gnutls_assert (); result = _gnutls_asn2err (result); goto cleanup; } if (raw == NULL) { gnutls_free (tmp); } else { raw->data = tmp; raw->size = tmp_size; } *sdata = c2; return 0; cleanup: if (c2) asn1_delete_structure (&c2); gnutls_free (tmp); return result; }
/* Converts a PKCS #8 private key info to * a PKCS #8 EncryptedPrivateKeyInfo. */ static int encode_to_pkcs8_key(schema_id schema, const gnutls_datum_t * der_key, const char *password, ASN1_TYPE * out) { int result; gnutls_datum_t key = { NULL, 0 }; gnutls_datum_t tmp = { NULL, 0 }; ASN1_TYPE pkcs8_asn = ASN1_TYPE_EMPTY; struct pbkdf2_params kdf_params; struct pbe_enc_params enc_params; const struct pkcs_cipher_schema_st *s; s = _gnutls_pkcs_schema_get(schema); if (s == NULL || s->decrypt_only) { return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); } if ((result = asn1_create_element(_gnutls_get_pkix(), "PKIX1.pkcs-8-EncryptedPrivateKeyInfo", &pkcs8_asn)) != ASN1_SUCCESS) { gnutls_assert(); return _gnutls_asn2err(result); } /* Write the encryption schema OID */ result = asn1_write_value(pkcs8_asn, "encryptionAlgorithm.algorithm", s->write_oid, 1); if (result != ASN1_SUCCESS) { gnutls_assert(); result = _gnutls_asn2err(result); goto error; } /* Generate a symmetric key. */ result = _gnutls_pkcs_generate_key(schema, password, &kdf_params, &enc_params, &key); if (result < 0) { gnutls_assert(); goto error; } result = _gnutls_pkcs_write_schema_params(schema, pkcs8_asn, "encryptionAlgorithm.parameters", &kdf_params, &enc_params); if (result < 0) { gnutls_assert(); goto error; } /* Parameters have been encoded. Now * encrypt the Data. */ result = _gnutls_pkcs_raw_encrypt_data(der_key, &enc_params, &key, &tmp); if (result < 0) { gnutls_assert(); goto error; } /* write the encrypted data. */ result = asn1_write_value(pkcs8_asn, "encryptedData", tmp.data, tmp.size); if (result != ASN1_SUCCESS) { gnutls_assert(); result = _gnutls_asn2err(result); goto error; } _gnutls_free_datum(&tmp); _gnutls_free_key_datum(&key); *out = pkcs8_asn; return 0; error: _gnutls_free_key_datum(&key); _gnutls_free_datum(&tmp); asn1_delete_structure2(&pkcs8_asn, ASN1_DELETE_FLAG_ZEROIZE); return result; }
static int pkcs8_key_info(const gnutls_datum_t * raw_key, const struct pkcs_cipher_schema_st **p, struct pbkdf2_params *kdf_params, char **oid) { int result, len; char enc_oid[MAX_OID_SIZE*2]; int params_start, params_end, params_len; struct pbe_enc_params enc_params; schema_id schema; ASN1_TYPE pkcs8_asn = ASN1_TYPE_EMPTY; memset(&enc_params, 0, sizeof(enc_params)); result = check_for_decrypted(raw_key); if (result == 0) return GNUTLS_E_INVALID_REQUEST; if ((result = asn1_create_element(_gnutls_get_pkix(), "PKIX1.pkcs-8-EncryptedPrivateKeyInfo", &pkcs8_asn)) != ASN1_SUCCESS) { gnutls_assert(); result = _gnutls_asn2err(result); goto error; } result = _asn1_strict_der_decode(&pkcs8_asn, raw_key->data, raw_key->size, NULL); if (result != ASN1_SUCCESS) { gnutls_assert(); result = _gnutls_asn2err(result); goto error; } /* Check the encryption schema OID */ len = sizeof(enc_oid); result = asn1_read_value(pkcs8_asn, "encryptionAlgorithm.algorithm", enc_oid, &len); if (result != ASN1_SUCCESS) { gnutls_assert(); goto error; } if (oid) { *oid = gnutls_strdup(enc_oid); } if ((result = _gnutls_check_pkcs_cipher_schema(enc_oid)) < 0) { gnutls_assert(); goto error; } schema = result; /* Get the DER encoding of the parameters. */ result = asn1_der_decoding_startEnd(pkcs8_asn, raw_key->data, raw_key->size, "encryptionAlgorithm.parameters", ¶ms_start, ¶ms_end); if (result != ASN1_SUCCESS) { gnutls_assert(); result = _gnutls_asn2err(result); goto error; } params_len = params_end - params_start + 1; result = _gnutls_read_pkcs_schema_params(&schema, NULL, &raw_key->data[params_start], params_len, kdf_params, &enc_params); if (result < 0) { gnutls_assert(); if (oid && enc_params.pbes2_oid[0] != 0) { snprintf(enc_oid, sizeof(enc_oid), "%s/%s", *oid, enc_params.pbes2_oid); gnutls_free(*oid); *oid = gnutls_strdup(enc_oid); } goto error; } *p = _gnutls_pkcs_schema_get(schema); if (*p == NULL) { gnutls_assert(); result = GNUTLS_E_UNKNOWN_CIPHER_TYPE; goto error; } result = 0; error: asn1_delete_structure2(&pkcs8_asn, ASN1_DELETE_FLAG_ZEROIZE); return result; }
/** * gnutls_x509_crl_get_authority_key_id: * @crl: should contain a #gnutls_x509_crl_t structure * @ret: The place where the identifier will be copied * @ret_size: Holds the size of the result field. * @critical: will be non zero if the extension is marked as critical * (may be null) * * This function will return the CRL authority's key identifier. This * is obtained by the X.509 Authority Key identifier extension field * (2.5.29.35). Note that this function only returns the * keyIdentifier field of the extension. * * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a * negative value in case of an error. * * Since: 2.8.0 **/ int gnutls_x509_crl_get_authority_key_id (gnutls_x509_crl_t crl, void *ret, size_t * ret_size, unsigned int *critical) { int result, len; gnutls_datum_t id; ASN1_TYPE c2 = ASN1_TYPE_EMPTY; if (crl == NULL) { gnutls_assert (); return GNUTLS_E_INVALID_REQUEST; } if (ret) memset (ret, 0, *ret_size); else *ret_size = 0; if ((result = _gnutls_x509_crl_get_extension (crl, "2.5.29.35", 0, &id, critical)) < 0) { return result; } if (id.size == 0 || id.data == NULL) { gnutls_assert (); return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; } result = asn1_create_element (_gnutls_get_pkix (), "PKIX1.AuthorityKeyIdentifier", &c2); if (result != ASN1_SUCCESS) { gnutls_assert (); _gnutls_free_datum (&id); return _gnutls_asn2err (result); } result = asn1_der_decoding (&c2, id.data, id.size, NULL); _gnutls_free_datum (&id); if (result != ASN1_SUCCESS) { gnutls_assert (); asn1_delete_structure (&c2); return _gnutls_asn2err (result); } len = *ret_size; result = asn1_read_value (c2, "keyIdentifier", ret, &len); *ret_size = len; asn1_delete_structure (&c2); if (result == ASN1_VALUE_NOT_FOUND || result == ASN1_ELEMENT_NOT_FOUND) { return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; } if (result != ASN1_SUCCESS) { gnutls_assert (); return _gnutls_asn2err (result); } return 0; }
static int decode_private_key_info(const gnutls_datum_t * der, gnutls_x509_privkey_t pkey) { int result, len; char oid[MAX_OID_SIZE]; ASN1_TYPE pkcs8_asn = ASN1_TYPE_EMPTY; gnutls_datum_t sder; int ret; if ((result = asn1_create_element(_gnutls_get_pkix(), "PKIX1.pkcs-8-PrivateKeyInfo", &pkcs8_asn)) != ASN1_SUCCESS) { gnutls_assert(); result = _gnutls_asn2err(result); goto error; } result = _asn1_strict_der_decode(&pkcs8_asn, der->data, der->size, NULL); if (result != ASN1_SUCCESS) { gnutls_assert(); result = _gnutls_asn2err(result); goto error; } /* Check the private key algorithm OID */ len = sizeof(oid); result = asn1_read_value(pkcs8_asn, "privateKeyAlgorithm.algorithm", oid, &len); if (result != ASN1_SUCCESS) { gnutls_assert(); result = _gnutls_asn2err(result); goto error; } pkey->params.algo = gnutls_oid_to_pk(oid); if (pkey->params.algo == GNUTLS_PK_UNKNOWN) { gnutls_assert(); _gnutls_debug_log ("PKCS #8 private key OID '%s' is unsupported.\n", oid); result = GNUTLS_E_UNKNOWN_PK_ALGORITHM; goto error; } /* Get the DER encoding of the actual private key. */ switch(pkey->params.algo) { case GNUTLS_PK_RSA: result = _decode_pkcs8_rsa_key(pkcs8_asn, pkey); break; case GNUTLS_PK_RSA_PSS: result = _decode_pkcs8_rsa_pss_key(pkcs8_asn, pkey); break; case GNUTLS_PK_DSA: result = _decode_pkcs8_dsa_key(pkcs8_asn, pkey); break; case GNUTLS_PK_ECDSA: result = _decode_pkcs8_ecc_key(pkcs8_asn, pkey); break; case GNUTLS_PK_EDDSA_ED25519: result = _decode_pkcs8_eddsa_key(pkcs8_asn, pkey, oid); break; case GNUTLS_PK_GOST_01: case GNUTLS_PK_GOST_12_256: case GNUTLS_PK_GOST_12_512: result = _decode_pkcs8_gost_key(pkcs8_asn, pkey, pkey->params.algo); break; default: result = gnutls_assert_val(GNUTLS_E_UNIMPLEMENTED_FEATURE); goto error; } if (result < 0) { gnutls_assert(); goto error; } /* check for provable parameters attribute */ ret = _x509_parse_attribute(pkcs8_asn, "attributes", OID_ATTR_PROV_SEED, 0, 1, &sder); if (ret >= 0) { /* ignore it when not being present */ ret = _x509_decode_provable_seed(pkey, &sder); gnutls_free(sder.data); if (ret < 0) { gnutls_assert(); } } result = 0; error: asn1_delete_structure2(&pkcs8_asn, ASN1_DELETE_FLAG_ZEROIZE); return result; }
/* Writes the digest information and the digest in a DER encoded * structure. The digest info is allocated and stored into the info structure. */ int encode_ber_digest_info(const mac_entry_st * e, const gnutls_datum_t * digest, gnutls_datum_t * output) { ASN1_TYPE dinfo = ASN1_TYPE_EMPTY; int result; const char *algo; uint8_t *tmp_output; int tmp_output_size; algo = _gnutls_x509_mac_to_oid(e); if (algo == NULL) { gnutls_assert(); _gnutls_debug_log("Hash algorithm: %d has no OID\n", e->id); return GNUTLS_E_UNKNOWN_PK_ALGORITHM; } if ((result = asn1_create_element(_gnutls_get_gnutls_asn(), "GNUTLS.DigestInfo", &dinfo)) != ASN1_SUCCESS) { gnutls_assert(); return _gnutls_asn2err(result); } result = asn1_write_value(dinfo, "digestAlgorithm.algorithm", algo, 1); if (result != ASN1_SUCCESS) { gnutls_assert(); asn1_delete_structure(&dinfo); return _gnutls_asn2err(result); } /* Write an ASN.1 NULL in the parameters field. This matches RFC 3279 and RFC 4055, although is arguable incorrect from a historic perspective (see those documents for more information). Regardless of what is correct, this appears to be what most implementations do. */ result = asn1_write_value(dinfo, "digestAlgorithm.parameters", ASN1_NULL, ASN1_NULL_SIZE); if (result != ASN1_SUCCESS) { gnutls_assert(); asn1_delete_structure(&dinfo); return _gnutls_asn2err(result); } result = asn1_write_value(dinfo, "digest", digest->data, digest->size); if (result != ASN1_SUCCESS) { gnutls_assert(); asn1_delete_structure(&dinfo); return _gnutls_asn2err(result); } tmp_output_size = 0; result = asn1_der_coding(dinfo, "", NULL, &tmp_output_size, NULL); if (result != ASN1_MEM_ERROR) { gnutls_assert(); asn1_delete_structure(&dinfo); return _gnutls_asn2err(result); } tmp_output = gnutls_malloc(tmp_output_size); if (tmp_output == NULL) { gnutls_assert(); asn1_delete_structure(&dinfo); return GNUTLS_E_MEMORY_ERROR; } result = asn1_der_coding(dinfo, "", tmp_output, &tmp_output_size, NULL); if (result != ASN1_SUCCESS) { gnutls_assert(); asn1_delete_structure(&dinfo); return _gnutls_asn2err(result); } asn1_delete_structure(&dinfo); output->size = tmp_output_size; output->data = tmp_output; return 0; }
/** * gnutls_decode_ber_digest_info: * @info: an RSA BER encoded DigestInfo structure * @hash: will contain the hash algorithm of the structure * @digest: will contain the hash output of the structure * @digest_size: will contain the hash size of the structure; initially must hold the maximum size of @digest * * This function will parse an RSA PKCS#1 1.5 DigestInfo structure * and report the hash algorithm used as well as the digest data. * * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise * an error code is returned. * * Since: 3.5.0 * **/ int gnutls_decode_ber_digest_info(const gnutls_datum_t * info, gnutls_digest_algorithm_t * hash, unsigned char * digest, unsigned int *digest_size) { ASN1_TYPE dinfo = ASN1_TYPE_EMPTY; int result; char str[MAX(MAX_OID_SIZE, MAX_HASH_SIZE)]; int len; if ((result = asn1_create_element(_gnutls_get_gnutls_asn(), "GNUTLS.DigestInfo", &dinfo)) != ASN1_SUCCESS) { gnutls_assert(); return _gnutls_asn2err(result); } result = asn1_der_decoding(&dinfo, info->data, info->size, NULL); if (result != ASN1_SUCCESS) { gnutls_assert(); asn1_delete_structure(&dinfo); return _gnutls_asn2err(result); } len = sizeof(str) - 1; result = asn1_read_value(dinfo, "digestAlgorithm.algorithm", str, &len); if (result != ASN1_SUCCESS) { gnutls_assert(); asn1_delete_structure(&dinfo); return _gnutls_asn2err(result); } *hash = gnutls_oid_to_digest(str); if (*hash == GNUTLS_DIG_UNKNOWN) { _gnutls_debug_log("verify.c: HASH OID: %s\n", str); gnutls_assert(); asn1_delete_structure(&dinfo); return GNUTLS_E_UNKNOWN_HASH_ALGORITHM; } len = sizeof(str) - 1; result = asn1_read_value(dinfo, "digestAlgorithm.parameters", str, &len); /* To avoid permitting garbage in the parameters field, either the parameters field is not present, or it contains 0x05 0x00. */ if (!(result == ASN1_ELEMENT_NOT_FOUND || (result == ASN1_SUCCESS && len == ASN1_NULL_SIZE && memcmp(str, ASN1_NULL, ASN1_NULL_SIZE) == 0))) { gnutls_assert(); asn1_delete_structure(&dinfo); return GNUTLS_E_ASN1_GENERIC_ERROR; } len = *digest_size; result = asn1_read_value(dinfo, "digest", digest, &len); if (result != ASN1_SUCCESS) { gnutls_assert(); *digest_size = len; asn1_delete_structure(&dinfo); return _gnutls_asn2err(result); } *digest_size = len; asn1_delete_structure(&dinfo); return 0; }
static int create_platf_manufacturer_info(const char *manufacturer, const char *platf_model, const char *platf_version, gnutls_datum_t *asn1) { ASN1_TYPE at = ASN1_TYPE_EMPTY; int err; err = asn_init(); if (err != ASN1_SUCCESS) { goto cleanup; } err = asn1_create_element(_tpm_asn, "TPM.PlatformManufacturerInfo", &at); if (err != ASN1_SUCCESS) { fprintf(stderr, "asn1_create_element error: %d\n", err); goto cleanup; } err = asn1_write_value(at, "platformManufacturer.id", "2.23.133.2.4", 0); if (err != ASN1_SUCCESS) { fprintf(stderr, "b1. asn1_write_value error: %d\n", err); goto cleanup; } err = asn1_write_value(at, "platformManufacturer.manufacturer", manufacturer, 0); if (err != ASN1_SUCCESS) { fprintf(stderr, "b2. asn1_write_value error: %d\n", err); goto cleanup; } err = asn1_write_value(at, "platformModel.id", "2.23.133.2.5", 0); if (err != ASN1_SUCCESS) { fprintf(stderr, "b3. asn1_write_value error: %d\n", err); goto cleanup; } err = asn1_write_value(at, "platformModel.model", manufacturer, 0); if (err != ASN1_SUCCESS) { fprintf(stderr, "b4. asn1_write_value error: %d\n", err); goto cleanup; } err = asn1_write_value(at, "platformVersion.id", "2.23.133.2.6", 0); if (err != ASN1_SUCCESS) { fprintf(stderr, "b5. asn1_write_value error: %d\n", err); goto cleanup; } err = asn1_write_value(at, "platformVersion.version", manufacturer, 0); if (err != ASN1_SUCCESS) { fprintf(stderr, "b6. asn1_write_value error: %d\n", err); goto cleanup; } /* determine needed size of byte array */ asn1->size = 0; err = asn1_der_coding(at, "", NULL, (int *)&asn1->size, NULL); if (err != ASN1_MEM_ERROR) { fprintf(stderr, "b1. asn1_der_coding error: %d\n", err); goto cleanup; } //fprintf(stderr, "size=%d\n", asn1->size); asn1->data = gnutls_malloc(asn1->size + 16); err = asn1_der_coding(at, "", asn1->data, (int *)&asn1->size, NULL); if (err != ASN1_SUCCESS) { fprintf(stderr, "b2. asn1_der_coding error: %d\n", err); gnutls_free(asn1->data); asn1->data = NULL; goto cleanup; } #if 0 fprintf(stderr, "size=%d\n", asn1->size); unsigned int i = 0; for (i = 0; i < asn1->size; i++) { fprintf(stderr, "%02x ", asn1->data[i]); } fprintf(stderr, "\n"); #endif cleanup: asn1_delete_structure(&at); return err; }
/* Creates and encodes the CRL Distribution points. data_string should be a name * and type holds the type of the name. * reason_flags should be an or'ed sequence of GNUTLS_CRL_REASON_*. * */ int _gnutls_x509_ext_gen_crl_dist_points(gnutls_x509_subject_alt_name_t type, const void *data, unsigned int data_size, unsigned int reason_flags, gnutls_datum_t * der_ext) { ASN1_TYPE ext = ASN1_TYPE_EMPTY; gnutls_datum_t gnames = { NULL, 0 }; int result; uint8_t reasons[2]; reasons[0] = reason_flags & 0xff; reasons[1] = reason_flags >> 8; result = asn1_create_element(_gnutls_get_pkix(), "PKIX1.CRLDistributionPoints", &ext); if (result != ASN1_SUCCESS) { gnutls_assert(); result = _gnutls_asn2err(result); goto cleanup; } result = asn1_write_value(ext, "", "NEW", 1); if (result != ASN1_SUCCESS) { gnutls_assert(); result = _gnutls_asn2err(result); goto cleanup; } if (reason_flags) { result = asn1_write_value(ext, "?LAST.reasons", reasons, 9); if (result != ASN1_SUCCESS) { gnutls_assert(); result = _gnutls_asn2err(result); goto cleanup; } } else { result = asn1_write_value(ext, "?LAST.reasons", NULL, 0); if (result != ASN1_SUCCESS) { gnutls_assert(); result = _gnutls_asn2err(result); goto cleanup; } } result = asn1_write_value(ext, "?LAST.cRLIssuer", NULL, 0); if (result != ASN1_SUCCESS) { gnutls_assert(); result = _gnutls_asn2err(result); goto cleanup; } /* When used as type CHOICE. */ result = asn1_write_value(ext, "?LAST.distributionPoint", "fullName", 1); if (result != ASN1_SUCCESS) { gnutls_assert(); result = _gnutls_asn2err(result); goto cleanup; } #if 0 /* only needed in old code (where defined as SEQUENCE OF) */ asn1_write_value(ext, "?LAST.distributionPoint.nameRelativeToCRLIssuer", NULL, 0); #endif result = write_new_general_name(ext, "?LAST.distributionPoint.fullName", type, data, data_size); if (result < 0) { gnutls_assert(); goto cleanup; } result = _gnutls_x509_der_encode(ext, "", der_ext, 0); if (result < 0) { gnutls_assert(); goto cleanup; } result = 0; cleanup: _gnutls_free_datum(&gnames); asn1_delete_structure(&ext); return result; }
int _gnutls_krb5_principal_to_der(const char *name, gnutls_datum_t * der) { int ret, result; ASN1_TYPE c2 = ASN1_TYPE_EMPTY; krb5_principal_data *princ; unsigned i; princ = name_to_principal(name); if (princ == NULL) { gnutls_assert(); ret = GNUTLS_E_PARSING_ERROR; goto cleanup; } result = asn1_create_element(_gnutls_get_gnutls_asn(), "GNUTLS.KRB5PrincipalName", &c2); if (result != ASN1_SUCCESS) { gnutls_assert(); ret = _gnutls_asn2err(result); goto cleanup; } result = asn1_write_value(c2, "realm", princ->realm, strlen(princ->realm)); if (result != ASN1_SUCCESS) { gnutls_assert(); ret = _gnutls_asn2err(result); goto cleanup; } result = asn1_write_value(c2, "principalName.name-type", &princ->type, 1); if (result != ASN1_SUCCESS) { gnutls_assert(); ret = _gnutls_asn2err(result); goto cleanup; } for (i = 0; i < princ->length; i++) { result = asn1_write_value(c2, "principalName.name-string", "NEW", 1); if (result != ASN1_SUCCESS) { gnutls_assert(); ret = _gnutls_asn2err(result); goto cleanup; } result = asn1_write_value(c2, "principalName.name-string.?LAST", princ->data[i], strlen(princ->data[i])); if (result != ASN1_SUCCESS) { gnutls_assert(); ret = _gnutls_asn2err(result); goto cleanup; } } ret = _gnutls_x509_der_encode(c2, "", der, 0); if (ret < 0) { gnutls_assert(); goto cleanup; } ret = 0; cleanup: cleanup_principal(princ); asn1_delete_structure(&c2); return ret; }
static gnutls_pubkey_t create_rsa_from_modulus(unsigned char *modulus, unsigned int modulus_len, uint32_t exponent) { unsigned char exp_array[4]; uint32_t exponent_no = htonl(exponent); gnutls_pubkey_t rsa = NULL; gnutls_datum_t mod; gnutls_datum_t exp = { .data = exp_array, .size = sizeof(exp_array), }; int err; memcpy(exp_array, &exponent_no, sizeof(exp_array)); err = gnutls_pubkey_init(&rsa); if (err < 0) { fprintf(stderr, "Could not initialized public key structure : %s\n", gnutls_strerror(err)); return NULL; } mod.data = modulus; mod.size = modulus_len; err = gnutls_pubkey_import_rsa_raw(rsa, &mod, &exp); if (err < 0) { fprintf(stderr, "Could not set modulus and exponent on RSA key : %s\n", gnutls_strerror(err)); gnutls_pubkey_deinit(rsa); rsa = NULL; } return rsa; } static int asn_init() { static bool inited; int err; if (inited) return ASN1_SUCCESS; err = asn1_array2tree(tpm_asn1_tab, &_tpm_asn, NULL); if (err != ASN1_SUCCESS) { fprintf(stderr, "array2tree error: %d", err); goto cleanup; } inited = true; cleanup: return err; } static int create_tpm_manufacturer_info(const char *manufacturer, const char *tpm_model, const char *tpm_version, gnutls_datum_t *asn1) { ASN1_TYPE at = ASN1_TYPE_EMPTY; int err; err = asn_init(); if (err != ASN1_SUCCESS) { goto cleanup; } err = asn1_create_element(_tpm_asn, "TPM.TPMManufacturerInfo", &at); if (err != ASN1_SUCCESS) { fprintf(stderr, "asn1_create_element error: %d\n", err); goto cleanup; } err = asn1_write_value(at, "tpmManufacturer.id", "2.23.133.2.1", 0); if (err != ASN1_SUCCESS) { fprintf(stderr, "1. asn1_write_value error: %d\n", err); goto cleanup; } err = asn1_write_value(at, "tpmManufacturer.manufacturer", manufacturer, 0); if (err != ASN1_SUCCESS) { fprintf(stderr, "2. asn1_write_value error: %d\n", err); goto cleanup; } err = asn1_write_value(at, "tpmModel.id", "2.23.133.2.2", 0); if (err != ASN1_SUCCESS) { fprintf(stderr, "3. asn1_write_value error: %d\n", err); goto cleanup; } err = asn1_write_value(at, "tpmModel.model", manufacturer, 0); if (err != ASN1_SUCCESS) { fprintf(stderr, "4. asn1_write_value error: %d\n", err); goto cleanup; } err = asn1_write_value(at, "tpmVersion.id", "2.23.133.2.3", 0); if (err != ASN1_SUCCESS) { fprintf(stderr, "5. asn1_write_value error: %d\n", err); goto cleanup; } err = asn1_write_value(at, "tpmVersion.version", manufacturer, 0); if (err != ASN1_SUCCESS) { fprintf(stderr, "6. asn1_write_value error: %d\n", err); goto cleanup; } /* determine needed size of byte array */ asn1->size = 0; err = asn1_der_coding(at, "", NULL, (int *)&asn1->size, NULL); if (err != ASN1_MEM_ERROR) { fprintf(stderr, "1. asn1_der_coding error: %d\n", err); goto cleanup; } //fprintf(stderr, "size=%d\n", asn1->size); asn1->data = gnutls_malloc(asn1->size + 16); err = asn1_der_coding(at, "", asn1->data, (int *)&asn1->size, NULL); if (err != ASN1_SUCCESS) { fprintf(stderr, "2. asn1_der_coding error: %d\n", err); gnutls_free(asn1->data); asn1->data = NULL; goto cleanup; } #if 0 fprintf(stderr, "size=%d\n", asn1->size); unsigned int i = 0; for (i = 0; i < asn1->size; i++) { fprintf(stderr, "%02x ", asn1->data[i]); } fprintf(stderr, "\n"); #endif cleanup: asn1_delete_structure(&at); return err; }
int main (int argc, char *argv[]) { int result, verbose = 0; asn1_node definitions = NULL; asn1_node asn1_element = NULL; char errorDescription[ASN1_MAX_ERROR_DESCRIPTION_SIZE]; const char *treefile = getenv ("ASN1SETOF"); unsigned i; if (argc > 1) verbose = 1; if (!treefile) treefile = "setof.asn"; if (verbose != 0) { printf ("\n\n/****************************************/\n"); printf ("/* Test sequence : coding-decoding */\n"); printf ("/****************************************/\n\n"); } /* Check version */ if (asn1_check_version ("0.3.3") == NULL) printf ("\nLibrary version check ERROR:\n actual version: %s\n\n", asn1_check_version (NULL)); result = asn1_parser2tree (treefile, &definitions, errorDescription); if (result != ASN1_SUCCESS) { asn1_perror (result); printf ("ErrorDescription = %s\n\n", errorDescription); exit (1); } result = asn1_create_element (definitions, "TEST.Set", &asn1_element); if (result != ASN1_SUCCESS) { fprintf (stderr, "asn1_create_element(): "); asn1_perror (result); exit (1); } result = asn1_write_value (asn1_element, "", "NEW", 1); assert(result == ASN1_SUCCESS); result = asn1_write_value (asn1_element, "?LAST.val", "\x00\x02", 2); assert(result == ASN1_SUCCESS); result = asn1_write_value (asn1_element, "", "NEW", 1); assert(result == ASN1_SUCCESS); result = asn1_write_value (asn1_element, "?LAST.val", "\x00\x01\x00\x00", 4); assert(result == ASN1_SUCCESS); result = asn1_write_value (asn1_element, "", "NEW", 1); assert(result == ASN1_SUCCESS); result = asn1_write_value (asn1_element, "?LAST.val", "\x00\x00\x00\x00", 4); assert(result == ASN1_SUCCESS); result = asn1_write_value (asn1_element, "", "NEW", 1); assert(result == ASN1_SUCCESS); result = asn1_write_value (asn1_element, "?LAST.val", "\x00\x00\x00\x02", 4); assert(result == ASN1_SUCCESS); result = asn1_write_value (asn1_element, "", "NEW", 1); assert(result == ASN1_SUCCESS); result = asn1_write_value (asn1_element, "?LAST.val", "\x00\x00\x00\x01", 4); assert(result == ASN1_SUCCESS); result = asn1_write_value (asn1_element, "", "NEW", 1); assert(result == ASN1_SUCCESS); result = asn1_write_value (asn1_element, "?LAST.val", "\x01\x00\x00\x00", 4); assert(result == ASN1_SUCCESS); result = asn1_write_value (asn1_element, "", "NEW", 1); assert(result == ASN1_SUCCESS); result = asn1_write_value (asn1_element, "?LAST.val", "\x01\x01\x00\x00", 4); assert(result == ASN1_SUCCESS); result = asn1_write_value (asn1_element, "", "NEW", 1); assert(result == ASN1_SUCCESS); result = asn1_write_value (asn1_element, "?LAST.val", "\x05", 1); assert(result == ASN1_SUCCESS); result = asn1_write_value (asn1_element, "", "NEW", 1); assert(result == ASN1_SUCCESS); result = asn1_write_value (asn1_element, "?LAST.val", "\x01", 1); assert(result == ASN1_SUCCESS); /* Clear the definition structures */ result = asn1_der_coding (asn1_element, "", data, &data_size, NULL); if (result != ASN1_SUCCESS) { fprintf (stderr, "Encoding error.\n"); asn1_perror (result); exit (1); } asn1_delete_structure (&asn1_element); asn1_delete_structure (&definitions); if (data_size != sizeof(expected_der) || memcmp(data, expected_der, data_size) != 0) { fprintf(stderr, "encoded data differ to expected [%d - %d]!\n", data_size, (int)sizeof(expected_der)); printf("static unsigned char got[] = {\n"); for (i=0;i<(unsigned)data_size;i++) { printf("0x%.2x, ", (unsigned)data[i]); if ((i+1) % 8 == 0) printf("\n"); } printf("};\n"); printf("static unsigned char expected[] = {\n"); for (i=0;i<(unsigned)sizeof(expected_der);i++) { printf("0x%.2x, ", (unsigned)expected_der[i]); if ((i+1) % 8 == 0) printf("\n"); } printf("};\n"); exit(1); } if (verbose) printf ("Success\n"); exit (0); }
static int decode_complex_string(const struct oid_to_string *oentry, void *value, int value_size, gnutls_datum_t * out) { char str[MAX_STRING_LEN], tmpname[128]; int len = -1, result; ASN1_TYPE tmpasn = ASN1_TYPE_EMPTY; char asn1_err[ASN1_MAX_ERROR_DESCRIPTION_SIZE] = ""; unsigned int etype; gnutls_datum_t td = {NULL, 0}; if (oentry->asn_desc == NULL) { gnutls_assert(); return GNUTLS_E_INTERNAL_ERROR; } if ((result = asn1_create_element(_gnutls_get_pkix(), oentry->asn_desc, &tmpasn)) != ASN1_SUCCESS) { gnutls_assert(); return _gnutls_asn2err(result); } if ((result = _asn1_strict_der_decode(&tmpasn, value, value_size, asn1_err)) != ASN1_SUCCESS) { gnutls_assert(); _gnutls_debug_log("_asn1_strict_der_decode: %s\n", asn1_err); asn1_delete_structure(&tmpasn); return _gnutls_asn2err(result); } /* Read the type of choice. */ len = sizeof(str) - 1; if ((result = asn1_read_value(tmpasn, "", str, &len)) != ASN1_SUCCESS) { /* CHOICE */ gnutls_assert(); asn1_delete_structure(&tmpasn); return _gnutls_asn2err(result); } str[len] = 0; /* We set the etype on the strings that may need * some conversion to UTF-8. The INVALID flag indicates * no conversion needed */ if (strcmp(str, "teletexString") == 0) etype = ASN1_ETYPE_TELETEX_STRING; else if (strcmp(str, "bmpString") == 0) etype = ASN1_ETYPE_BMP_STRING; else if (strcmp(str, "universalString") == 0) etype = ASN1_ETYPE_UNIVERSAL_STRING; else etype = ASN1_ETYPE_INVALID; _gnutls_str_cpy(tmpname, sizeof(tmpname), str); result = _gnutls_x509_read_value(tmpasn, tmpname, &td); asn1_delete_structure(&tmpasn); if (result < 0) return gnutls_assert_val(result); if (etype != ASN1_ETYPE_INVALID) { result = make_printable_string(etype, &td, out); _gnutls_free_datum(&td); if (result < 0) return gnutls_assert_val(result); } else { out->data = td.data; out->size = td.size; /* _gnutls_x509_read_value always null terminates */ } /* Refuse to deal with strings containing NULs. */ if (strlen((void *) out->data) != (size_t) out->size) { _gnutls_free_datum(out); return gnutls_assert_val(GNUTLS_E_ASN1_EMBEDDED_NULL_IN_STRING); } return 0; }
static int write_complex_string(ASN1_TYPE asn_struct, const char *where, const struct oid_to_string *oentry, const uint8_t * data, size_t data_size) { char tmp[128]; ASN1_TYPE c2; int result; const char *string_type; unsigned int i; result = asn1_create_element(_gnutls_get_pkix(), oentry->asn_desc, &c2); if (result != ASN1_SUCCESS) { gnutls_assert(); return _gnutls_asn2err(result); } tmp[0] = 0; string_type = "printableString"; /* Check if the data is ASN.1 printable, and use * the UTF8 string type if not. */ for (i = 0; i < data_size; i++) { if (!is_printable(data[i])) { string_type = "utf8String"; break; } } /* if the type is a CHOICE then write the * type we'll use. */ result = asn1_write_value(c2, "", string_type, 1); if (result != ASN1_SUCCESS) { gnutls_assert(); result = _gnutls_asn2err(result); goto error; } _gnutls_str_cpy(tmp, sizeof(tmp), string_type); result = asn1_write_value(c2, tmp, data, data_size); if (result != ASN1_SUCCESS) { gnutls_assert(); result = _gnutls_asn2err(result); goto error; } result = _gnutls_x509_der_encode_and_copy(c2, "", asn_struct, where, 0); if (result < 0) { gnutls_assert(); goto error; } result = 0; error: asn1_delete_structure(&c2); return result; }
static int negotiate(smb_session *s, const char *domain) { smb_message *msg = NULL; smb_session_xsec_req req; smb_buffer ntlm; ASN1_TYPE token; int res, der_size = 128; char der[128], err_desc[ASN1_MAX_ERROR_DESCRIPTION_SIZE]; msg = smb_message_new(SMB_CMD_SETUP); if (!msg) return DSM_ERROR_GENERIC; // this struct will be set at the end when we know the payload size SMB_MSG_ADVANCE_PKT(msg, smb_session_xsec_req); asn1_create_element(s->spnego_asn1, "SPNEGO.GSSAPIContextToken", &token); res = asn1_write_value(token, "thisMech", spnego_oid, 1); if (res != ASN1_SUCCESS) goto error; res = asn1_write_value(token, "spnego", "negTokenInit", 1); if (res != ASN1_SUCCESS) goto error; res = asn1_write_value(token, "spnego.negTokenInit.mechTypes", "NEW", 1); if (res != ASN1_SUCCESS) goto error; res = asn1_write_value(token, "spnego.negTokenInit.mechTypes.?1", ntlmssp_oid, 1); if (res != ASN1_SUCCESS) goto error; res = asn1_write_value(token, "spnego.negTokenInit.reqFlags", NULL, 0); if (res != ASN1_SUCCESS) goto error; res = asn1_write_value(token, "spnego.negTokenInit.mechListMIC", NULL, 0); if (res != ASN1_SUCCESS) goto error; smb_ntlmssp_negotiate(domain, domain, &ntlm); res = asn1_write_value(token, "spnego.negTokenInit.mechToken", ntlm.data, ntlm.size); smb_buffer_free(&ntlm); if (res != ASN1_SUCCESS) goto error; res = asn1_der_coding(token, "", der, &der_size, err_desc); if (res != ASN1_SUCCESS) { smb_message_destroy(msg); BDSM_dbg("Encoding error: %s", err_desc); return DSM_ERROR_GENERIC; } smb_message_append(msg, der, der_size); smb_message_put_utf16(msg, SMB_OS, strlen(SMB_OS)); smb_message_put16(msg, 0); smb_message_put_utf16(msg, SMB_LANMAN, strlen(SMB_LANMAN)); smb_message_put16(msg, 0); smb_message_put16(msg, 0); SMB_MSG_INIT_PKT_ANDX(req); req.wct = 12; req.max_buffer = SMB_SESSION_MAX_BUFFER; req.mpx_count = 16; req.vc_count = 1; req.caps = s->srv.caps; req.session_key = s->srv.session_key; req.xsec_blob_size = der_size; req.payload_size = msg->cursor - sizeof(smb_session_xsec_req); SMB_MSG_INSERT_PKT(msg, 0, req); asn1_delete_structure(&token); if (!smb_session_send_msg(s, msg)) { smb_message_destroy(msg); BDSM_dbg("Unable to send Session Setup AndX (NTLMSSP_NEGOTIATE) message\n"); return DSM_ERROR_NETWORK; } smb_message_destroy(msg); return DSM_SUCCESS; error: asn1_display_error("smb_session_login negotiate()", res); smb_message_destroy(msg); return DSM_ERROR_GENERIC; }
/* extract the proxyCertInfo from the DER encoded extension */ int _gnutls_x509_ext_extract_proxyCertInfo(int *pathLenConstraint, char **policyLanguage, char **policy, size_t * sizeof_policy, uint8_t * extnValue, int extnValueLen) { ASN1_TYPE ext = ASN1_TYPE_EMPTY; int result; gnutls_datum_t value; if ((result = asn1_create_element (_gnutls_get_pkix(), "PKIX1.ProxyCertInfo", &ext)) != ASN1_SUCCESS) { gnutls_assert(); return _gnutls_asn2err(result); } result = asn1_der_decoding(&ext, extnValue, extnValueLen, NULL); if (result != ASN1_SUCCESS) { gnutls_assert(); asn1_delete_structure(&ext); return _gnutls_asn2err(result); } if (pathLenConstraint) { result = _gnutls_x509_read_uint(ext, "pCPathLenConstraint", (unsigned int *) pathLenConstraint); if (result == GNUTLS_E_ASN1_ELEMENT_NOT_FOUND) *pathLenConstraint = -1; else if (result != GNUTLS_E_SUCCESS) { asn1_delete_structure(&ext); return _gnutls_asn2err(result); } } result = _gnutls_x509_read_value(ext, "proxyPolicy.policyLanguage", &value); if (result < 0) { gnutls_assert(); asn1_delete_structure(&ext); return result; } if (policyLanguage) *policyLanguage = gnutls_strdup((char *) value.data); result = _gnutls_x509_read_value(ext, "proxyPolicy.policy", &value); if (result == GNUTLS_E_ASN1_ELEMENT_NOT_FOUND) { if (policy) *policy = NULL; if (sizeof_policy) *sizeof_policy = 0; } else if (result < 0) { gnutls_assert(); asn1_delete_structure(&ext); return result; } else { if (policy) *policy = (char *) value.data; if (sizeof_policy) *sizeof_policy = value.size; } asn1_delete_structure(&ext); return 0; }
/* This will encode and write the AttributeTypeAndValue field. * 'multi' must be zero if writing an AttributeTypeAndValue, and 1 if Attribute. * In all cases only one value is written. */ int _gnutls_x509_encode_and_write_attribute (const char *given_oid, ASN1_TYPE asn1_struct, const char *where, const void *_data, int sizeof_data, int multi) { const char *val_name; const opaque *data = _data; char tmp[128]; ASN1_TYPE c2; int result; /* Find how to encode the data. */ val_name = asn1_find_structure_from_oid (_gnutls_get_pkix (), given_oid); if (val_name == NULL) { gnutls_assert (); return GNUTLS_E_X509_UNSUPPORTED_OID; } _gnutls_str_cpy (tmp, sizeof (tmp), "PKIX1."); _gnutls_str_cat (tmp, sizeof (tmp), val_name); result = asn1_create_element (_gnutls_get_pkix (), tmp, &c2); if (result != ASN1_SUCCESS) { gnutls_assert (); return _gnutls_asn2err (result); } tmp[0] = 0; if ((result = _gnutls_x509_oid_data_choice (given_oid)) > 0) { char *string_type; int i; string_type = "printableString"; /* Check if the data is plain ascii, and use * the UTF8 string type if not. */ for (i = 0; i < sizeof_data; i++) { if (!isascii (data[i])) { string_type = "utf8String"; break; } } /* if the type is a CHOICE then write the * type we'll use. */ result = asn1_write_value (c2, "", string_type, 1); if (result != ASN1_SUCCESS) { gnutls_assert (); asn1_delete_structure (&c2); return _gnutls_asn2err (result); } _gnutls_str_cpy (tmp, sizeof (tmp), string_type); } result = asn1_write_value (c2, tmp, data, sizeof_data); if (result != ASN1_SUCCESS) { gnutls_assert (); asn1_delete_structure (&c2); return _gnutls_asn2err (result); } /* write the data (value) */ _gnutls_str_cpy (tmp, sizeof (tmp), where); _gnutls_str_cat (tmp, sizeof (tmp), ".value"); if (multi != 0) { /* if not writing an AttributeTypeAndValue, but an Attribute */ _gnutls_str_cat (tmp, sizeof (tmp), "s"); /* values */ result = asn1_write_value (asn1_struct, tmp, "NEW", 1); if (result != ASN1_SUCCESS) { gnutls_assert (); return _gnutls_asn2err (result); } _gnutls_str_cat (tmp, sizeof (tmp), ".?LAST"); } result = _gnutls_x509_der_encode_and_copy (c2, "", asn1_struct, tmp, 0); if (result < 0) { gnutls_assert (); return result; } /* write the type */ _gnutls_str_cpy (tmp, sizeof (tmp), where); _gnutls_str_cat (tmp, sizeof (tmp), ".type"); result = asn1_write_value (asn1_struct, tmp, given_oid, 1); if (result != ASN1_SUCCESS) { gnutls_assert (); return _gnutls_asn2err (result); } return 0; }
int _gnutls_x509_crq_set_extension(gnutls_x509_crq_t crq, const char *ext_id, const gnutls_datum_t * ext_data, unsigned int critical) { unsigned char *extensions = NULL; size_t extensions_size = 0; gnutls_datum_t der; ASN1_TYPE c2; int result; result = gnutls_x509_crq_get_attribute_by_oid(crq, "1.2.840.113549.1.9.14", 0, NULL, &extensions_size); if (result == GNUTLS_E_SHORT_MEMORY_BUFFER) { extensions = gnutls_malloc(extensions_size); if (extensions == NULL) { gnutls_assert(); return GNUTLS_E_MEMORY_ERROR; } result = gnutls_x509_crq_get_attribute_by_oid(crq, "1.2.840.113549.1.9.14", 0, extensions, &extensions_size); } if (result < 0) { if (result == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) { extensions_size = 0; } else { gnutls_assert(); gnutls_free(extensions); return result; } } result = asn1_create_element(_gnutls_get_pkix(), "PKIX1.Extensions", &c2); if (result != ASN1_SUCCESS) { gnutls_assert(); gnutls_free(extensions); return _gnutls_asn2err(result); } if (extensions_size > 0) { result = asn1_der_decoding(&c2, extensions, extensions_size, NULL); gnutls_free(extensions); if (result != ASN1_SUCCESS) { gnutls_assert(); asn1_delete_structure(&c2); return _gnutls_asn2err(result); } } result = set_extension(c2, "", ext_id, ext_data, critical); if (result < 0) { gnutls_assert(); asn1_delete_structure(&c2); return result; } result = _gnutls_x509_der_encode(c2, "", &der, 0); asn1_delete_structure(&c2); if (result < 0) { gnutls_assert(); return result; } result = gnutls_x509_crq_set_attribute_by_oid(crq, "1.2.840.113549.1.9.14", der.data, der.size); gnutls_free(der.data); if (result < 0) { gnutls_assert(); return result; } return 0; }
/* encodes the Dss-Sig-Value structure */ int _gnutls_encode_ber_rs_raw(gnutls_datum_t * sig_value, const gnutls_datum_t * r, const gnutls_datum_t * s) { ASN1_TYPE sig; int result, ret; uint8_t *tmp = NULL; if ((result = asn1_create_element(_gnutls_get_gnutls_asn(), "GNUTLS.DSASignatureValue", &sig)) != ASN1_SUCCESS) { gnutls_assert(); return _gnutls_asn2err(result); } if (s->data[0] >= 0x80 || r->data[0] >= 0x80) { tmp = gnutls_malloc(MAX(r->size, s->size)+1); if (tmp == NULL) { ret = gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); goto cleanup; } } if (r->data[0] >= 0x80) { tmp[0] = 0; memcpy(&tmp[1], r->data, r->size); result = asn1_write_value(sig, "r", tmp, 1+r->size); } else { result = asn1_write_value(sig, "r", r->data, r->size); } if (result != ASN1_SUCCESS) { gnutls_assert(); ret = _gnutls_asn2err(result); goto cleanup; } if (s->data[0] >= 0x80) { tmp[0] = 0; memcpy(&tmp[1], s->data, s->size); result = asn1_write_value(sig, "s", tmp, 1+s->size); } else { result = asn1_write_value(sig, "s", s->data, s->size); } if (result != ASN1_SUCCESS) { gnutls_assert(); ret = _gnutls_asn2err(result); goto cleanup; } ret = _gnutls_x509_der_encode(sig, "", sig_value, 0); if (ret < 0) { gnutls_assert(); goto cleanup; } ret = 0; cleanup: gnutls_free(tmp); asn1_delete_structure(&sig); return ret; }
/* Writes the value of the datum in the given ASN1_TYPE. If str is non * zero it encodes it as OCTET STRING. */ int _gnutls_x509_write_value (ASN1_TYPE c, const char *root, const gnutls_datum_t * data, int str) { int result; int asize; ASN1_TYPE c2 = ASN1_TYPE_EMPTY; gnutls_datum_t val; asize = data->size + 16; val.data = gnutls_malloc (asize); if (val.data == NULL) { gnutls_assert (); result = GNUTLS_E_MEMORY_ERROR; goto cleanup; } if (str) { /* Convert it to OCTET STRING */ if ((result = asn1_create_element (_gnutls_get_pkix (), "PKIX1.pkcs-7-Data", &c2)) != ASN1_SUCCESS) { gnutls_assert (); result = _gnutls_asn2err (result); goto cleanup; } result = asn1_write_value (c2, "", data->data, data->size); if (result != ASN1_SUCCESS) { gnutls_assert (); result = _gnutls_asn2err (result); goto cleanup; } result = _gnutls_x509_der_encode (c2, "", &val, 0); if (result < 0) { gnutls_assert (); goto cleanup; } } else { val.data = data->data; val.size = data->size; } /* Write the data. */ result = asn1_write_value (c, root, val.data, val.size); if (val.data != data->data) _gnutls_free_datum (&val); if (result != ASN1_SUCCESS) { gnutls_assert (); return _gnutls_asn2err (result); } return 0; cleanup: if (val.data != data->data) _gnutls_free_datum (&val); return result; }
/** * gnutls_x509_crl_get_raw_issuer_dn: * @crl: should contain a gnutls_x509_crl_t structure * @dn: will hold the starting point of the DN * * This function will return a pointer to the DER encoded DN structure * and the length. * * Returns: a negative value on error, and zero on success. * * Since: 2.12.0 **/ int gnutls_x509_crl_get_raw_issuer_dn (gnutls_x509_crl_t crl, gnutls_datum_t * dn) { ASN1_TYPE c2 = ASN1_TYPE_EMPTY; int result, len1; int start1, end1; gnutls_datum_t crl_signed_data; if (crl == NULL) { gnutls_assert (); return GNUTLS_E_INVALID_REQUEST; } /* get the issuer of 'crl' */ if ((result = asn1_create_element (_gnutls_get_pkix (), "PKIX1.TBSCertList", &c2)) != ASN1_SUCCESS) { gnutls_assert (); return _gnutls_asn2err (result); } result = _gnutls_x509_get_signed_data (crl->crl, "tbsCertList", &crl_signed_data); if (result < 0) { gnutls_assert (); goto cleanup; } result = asn1_der_decoding (&c2, crl_signed_data.data, crl_signed_data.size, NULL); if (result != ASN1_SUCCESS) { /* couldn't decode DER */ gnutls_assert (); asn1_delete_structure (&c2); result = _gnutls_asn2err (result); goto cleanup; } result = asn1_der_decoding_startEnd (c2, crl_signed_data.data, crl_signed_data.size, "issuer", &start1, &end1); if (result != ASN1_SUCCESS) { gnutls_assert (); result = _gnutls_asn2err (result); goto cleanup; } len1 = end1 - start1 + 1; _gnutls_set_datum (dn, &crl_signed_data.data[start1], len1); result = 0; cleanup: asn1_delete_structure (&c2); _gnutls_free_datum (&crl_signed_data); return result; }
/* This function will convert an attribute value, specified by the OID, * to a string. The result will be a null terminated string. * * res may be null. This will just return the res_size, needed to * hold the string. */ int _gnutls_x509_oid_data2string (const char *oid, void *value, int value_size, char *res, size_t * res_size) { char str[MAX_STRING_LEN], tmpname[128]; const char *ANAME = NULL; int CHOICE = -1, len = -1, result; ASN1_TYPE tmpasn = ASN1_TYPE_EMPTY; if (value == NULL || value_size <= 0 || res_size == NULL) { gnutls_assert (); return GNUTLS_E_INVALID_REQUEST; } if (_gnutls_x509_oid_data_printable (oid) == 0) { gnutls_assert (); return GNUTLS_E_INTERNAL_ERROR; } ANAME = asn1_find_structure_from_oid (_gnutls_get_pkix (), oid); CHOICE = _gnutls_x509_oid_data_choice (oid); if (ANAME == NULL) { gnutls_assert (); return GNUTLS_E_INTERNAL_ERROR; } _gnutls_str_cpy (str, sizeof (str), "PKIX1."); _gnutls_str_cat (str, sizeof (str), ANAME); if ((result = asn1_create_element (_gnutls_get_pkix (), str, &tmpasn)) != ASN1_SUCCESS) { gnutls_assert (); return _gnutls_asn2err (result); } if ((result = asn1_der_decoding (&tmpasn, value, value_size, NULL)) != ASN1_SUCCESS) { gnutls_assert (); asn1_delete_structure (&tmpasn); return _gnutls_asn2err (result); } /* If this is a choice then we read the choice. Otherwise it * is the value; */ len = sizeof (str) - 1; if ((result = asn1_read_value (tmpasn, "", str, &len)) != ASN1_SUCCESS) { /* CHOICE */ gnutls_assert (); asn1_delete_structure (&tmpasn); return _gnutls_asn2err (result); } if (CHOICE == 0) { str[len] = 0; if (res) _gnutls_str_cpy (res, *res_size, str); *res_size = len; asn1_delete_structure (&tmpasn); } else { /* CHOICE */ int non_printable = 0, teletex = 0; str[len] = 0; /* Note that we do not support strings other than * UTF-8 (thus ASCII as well). */ if (strcmp (str, "printableString") != 0 && strcmp (str, "utf8String") != 0) { non_printable = 1; } if (strcmp (str, "teletexString") == 0) teletex = 1; _gnutls_str_cpy (tmpname, sizeof (tmpname), str); len = sizeof (str) - 1; if ((result = asn1_read_value (tmpasn, tmpname, str, &len)) != ASN1_SUCCESS) { asn1_delete_structure (&tmpasn); return _gnutls_asn2err (result); } asn1_delete_structure (&tmpasn); if (teletex != 0) { int ascii = 0, i; /* HACK: if the teletex string contains only ascii * characters then treat it as printable. */ for (i = 0; i < len; i++) if (!isascii (str[i])) ascii = 1; if (ascii == 0) non_printable = 0; } if (res) { if (non_printable == 0) { str[len] = 0; _gnutls_str_cpy (res, *res_size, str); *res_size = len; } else { result = _gnutls_x509_data2hex (str, len, res, res_size); if (result < 0) { gnutls_assert (); return result; } } } } return 0; }
/* Converts a GOST key to * an internal structure (gnutls_private_key) */ static int _privkey_decode_gost_key(const gnutls_datum_t * raw_key, gnutls_x509_privkey_t pkey) { int ret; int ecc_size = gnutls_ecc_curve_get_size(pkey->params.curve); /* Just to be sure here */ if (ecc_size <= 0) { gnutls_assert(); ret = GNUTLS_E_ECC_UNSUPPORTED_CURVE; goto error; } /* Private key form described in R 50.1.112-2016. * Private key can come up as masked value concatenated with several masks. * each part is of ecc_size bytes. Key will be unmasked in pk_fixup */ if (raw_key->size % ecc_size == 0) { ret = _gnutls_mpi_init_scan_le(&pkey->params.params[GOST_K], raw_key->data, raw_key->size); if (ret < 0) { gnutls_assert(); goto error; } } else if (raw_key->data[0] == ASN1_TAG_INTEGER) { ASN1_TYPE pkey_asn; /* Very old format: INTEGER packed in OCTET STRING */ if ((ret = asn1_create_element(_gnutls_get_gnutls_asn(), "GNUTLS.GOSTPrivateKeyOld", &pkey_asn)) != ASN1_SUCCESS) { gnutls_assert(); ret = _gnutls_asn2err(ret); goto error; } ret = _asn1_strict_der_decode(&pkey_asn, raw_key->data, raw_key->size, NULL); if (ret != ASN1_SUCCESS) { gnutls_assert(); ret = _gnutls_asn2err(ret); asn1_delete_structure2(&pkey_asn, ASN1_DELETE_FLAG_ZEROIZE); goto error; } ret = _gnutls_x509_read_key_int(pkey_asn, "", &pkey->params.params[GOST_K]); if (ret < 0) { gnutls_assert(); asn1_delete_structure2(&pkey_asn, ASN1_DELETE_FLAG_ZEROIZE); goto error; } asn1_delete_structure2(&pkey_asn, ASN1_DELETE_FLAG_ZEROIZE); } else if (raw_key->data[0] == ASN1_TAG_OCTET_STRING) { ASN1_TYPE pkey_asn; /* format: OCTET STRING packed in OCTET STRING */ if ((ret = asn1_create_element(_gnutls_get_gnutls_asn(), "GNUTLS.GOSTPrivateKey", &pkey_asn)) != ASN1_SUCCESS) { gnutls_assert(); ret = _gnutls_asn2err(ret); goto error; } ret = _asn1_strict_der_decode(&pkey_asn, raw_key->data, raw_key->size, NULL); if (ret != ASN1_SUCCESS) { gnutls_assert(); ret = _gnutls_asn2err(ret); asn1_delete_structure2(&pkey_asn, ASN1_DELETE_FLAG_ZEROIZE); goto error; } ret = _gnutls_x509_read_key_int_le(pkey_asn, "", &pkey->params.params[GOST_K]); if (ret < 0) { gnutls_assert(); asn1_delete_structure2(&pkey_asn, ASN1_DELETE_FLAG_ZEROIZE); goto error; } asn1_delete_structure2(&pkey_asn, ASN1_DELETE_FLAG_ZEROIZE); } else { gnutls_assert(); ret = GNUTLS_E_PARSING_ERROR; goto error; } pkey->params.params_nr++; return 0; error: return ret; }
/* DER Encodes the src ASN1_TYPE and stores it to * the given datum. If str is non null then the data are encoded as * an OCTET STRING. */ int _gnutls_x509_der_encode (ASN1_TYPE src, const char *src_name, gnutls_datum_t * res, int str) { int size, result; int asize; opaque *data = NULL; ASN1_TYPE c2 = ASN1_TYPE_EMPTY; size = 0; result = asn1_der_coding (src, src_name, NULL, &size, NULL); if (result != ASN1_MEM_ERROR) { gnutls_assert (); result = _gnutls_asn2err (result); goto cleanup; } /* allocate data for the der */ if (str) size += 16; /* for later to include the octet tags */ asize = size; data = gnutls_malloc (size); if (data == NULL) { gnutls_assert (); result = GNUTLS_E_MEMORY_ERROR; goto cleanup; } result = asn1_der_coding (src, src_name, data, &size, NULL); if (result != ASN1_SUCCESS) { gnutls_assert (); result = _gnutls_asn2err (result); goto cleanup; } if (str) { if ((result = asn1_create_element (_gnutls_get_pkix (), "PKIX1.pkcs-7-Data", &c2)) != ASN1_SUCCESS) { gnutls_assert (); result = _gnutls_asn2err (result); goto cleanup; } result = asn1_write_value (c2, "", data, size); if (result != ASN1_SUCCESS) { gnutls_assert (); result = _gnutls_asn2err (result); goto cleanup; } result = asn1_der_coding (c2, "", data, &asize, NULL); if (result != ASN1_SUCCESS) { gnutls_assert (); result = _gnutls_asn2err (result); goto cleanup; } size = asize; asn1_delete_structure (&c2); } res->data = data; res->size = size; return 0; cleanup: gnutls_free (data); asn1_delete_structure (&c2); return result; }
/* * Encodes a PKCS #1 private key to a PKCS #8 private key * info. The output will be allocated and stored into der. Also * the ASN1_TYPE of private key info will be returned. */ static int encode_to_private_key_info(gnutls_x509_privkey_t pkey, gnutls_datum_t * der, ASN1_TYPE * pkey_info) { int result, len; uint8_t null = 0; const char *oid; gnutls_datum_t algo_params = { NULL, 0 }; gnutls_datum_t algo_privkey = { NULL, 0 }; oid = gnutls_pk_get_oid(pkey->params.algo); if (oid == NULL) { gnutls_assert(); return GNUTLS_E_UNIMPLEMENTED_FEATURE; } result = _gnutls_x509_write_pubkey_params(&pkey->params, &algo_params); if (result < 0) { gnutls_assert(); return result; } if ((result = asn1_create_element(_gnutls_get_pkix(), "PKIX1.pkcs-8-PrivateKeyInfo", pkey_info)) != ASN1_SUCCESS) { gnutls_assert(); result = _gnutls_asn2err(result); goto error; } /* Write the version. */ result = asn1_write_value(*pkey_info, "version", &null, 1); if (result != ASN1_SUCCESS) { gnutls_assert(); result = _gnutls_asn2err(result); goto error; } /* write the privateKeyAlgorithm * fields. (OID+NULL data) */ result = asn1_write_value(*pkey_info, "privateKeyAlgorithm.algorithm", oid, 1); if (result != ASN1_SUCCESS) { gnutls_assert(); result = _gnutls_asn2err(result); goto error; } result = asn1_write_value(*pkey_info, "privateKeyAlgorithm.parameters", algo_params.data, algo_params.size); _gnutls_free_key_datum(&algo_params); if (result != ASN1_SUCCESS) { gnutls_assert(); result = _gnutls_asn2err(result); goto error; } /* Write the raw private key */ result = _encode_privkey(pkey, &algo_privkey); if (result < 0) { gnutls_assert(); goto error; } result = asn1_write_value(*pkey_info, "privateKey", algo_privkey.data, algo_privkey.size); _gnutls_free_key_datum(&algo_privkey); if (result != ASN1_SUCCESS) { gnutls_assert(); result = _gnutls_asn2err(result); goto error; } if ((pkey->params.pkflags & GNUTLS_PK_FLAG_PROVABLE) && pkey->params.seed_size > 0) { gnutls_datum_t seed_info; /* rfc8479 attribute encoding */ result = _x509_encode_provable_seed(pkey, &seed_info); if (result < 0) { gnutls_assert(); goto error; } result = _x509_set_attribute(*pkey_info, "attributes", OID_ATTR_PROV_SEED, &seed_info); gnutls_free(seed_info.data); if (result < 0) { gnutls_assert(); goto error; } } else { /* Append an empty Attributes field. */ result = asn1_write_value(*pkey_info, "attributes", NULL, 0); if (result != ASN1_SUCCESS) { gnutls_assert(); result = _gnutls_asn2err(result); goto error; } } /* DER Encode the generated private key info. */ len = 0; result = asn1_der_coding(*pkey_info, "", NULL, &len, NULL); if (result != ASN1_MEM_ERROR) { gnutls_assert(); result = _gnutls_asn2err(result); goto error; } /* allocate data for the der */ der->size = len; der->data = gnutls_malloc(len); if (der->data == NULL) { gnutls_assert(); return GNUTLS_E_MEMORY_ERROR; } result = asn1_der_coding(*pkey_info, "", der->data, &len, NULL); if (result != ASN1_SUCCESS) { gnutls_assert(); result = _gnutls_asn2err(result); goto error; } return 0; error: asn1_delete_structure2(pkey_info, ASN1_DELETE_FLAG_ZEROIZE); _gnutls_free_datum(&algo_params); _gnutls_free_key_datum(&algo_privkey); return result; }
static int challenge(smb_session *s) { char err_desc[ASN1_MAX_ERROR_DESCRIPTION_SIZE]; char resp_token[256]; smb_message msg; smb_session_xsec_resp *resp; smb_ntlmssp_challenge *challenge; ASN1_TYPE token; int res, resp_token_size = 256; assert(s != NULL); if (smb_session_recv_msg(s, &msg) == 0) { BDSM_dbg("spnego challenge(): Unable to receive message\n"); return DSM_ERROR_NETWORK; } if (msg.packet->header.status != NT_STATUS_MORE_PROCESSING_REQUIRED) { BDSM_dbg("spnego challenge(): Bad status (0x%x)\n", msg.packet->header.status); return DSM_ERROR_GENERIC; } resp = (smb_session_xsec_resp *)msg.packet->payload; asn1_create_element(s->spnego_asn1, "SPNEGO.NegotiationToken", &token); res = asn1_der_decoding(&token, resp->payload, resp->xsec_blob_size, err_desc); if (res != ASN1_SUCCESS) { asn1_delete_structure(&token); asn1_display_error("NegTokenResp parsing", res); BDSM_dbg("Parsing error detail: %s\n", err_desc); return DSM_ERROR_GENERIC; } // XXX Check the value of "negTokenResp.negResult" res = asn1_read_value(token, "negTokenResp.responseToken", resp_token, &resp_token_size); asn1_delete_structure(&token); if (res != ASN1_SUCCESS) { asn1_display_error("NegTokenResp read responseToken", res); return DSM_ERROR_GENERIC; } // We got the server challenge, yeaaah. challenge = (smb_ntlmssp_challenge *)resp_token; if (smb_buffer_alloc(&s->xsec_target, challenge->tgt_len) == 0) return DSM_ERROR_GENERIC; memcpy(s->xsec_target.data, challenge->data + challenge->tgt_offset - sizeof(smb_ntlmssp_challenge), s->xsec_target.size); s->srv.challenge = challenge->challenge; s->srv.uid = msg.packet->header.uid; BDSM_dbg("Server challenge is 0x%"PRIx64"\n", s->srv.challenge); return DSM_SUCCESS; }
/* Encodes a private key to the raw format PKCS #8 needs. * For RSA it is a PKCS #1 DER private key and for DSA it is * an ASN.1 INTEGER of the x value. */ inline static int _encode_privkey(gnutls_x509_privkey_t pkey, gnutls_datum_t * raw) { int ret; ASN1_TYPE spk = ASN1_TYPE_EMPTY; switch (pkey->params.algo) { case GNUTLS_PK_EDDSA_ED25519: /* we encode as octet string (which is going to be stored inside * another octet string). No comments. */ ret = _gnutls_x509_encode_string(ASN1_ETYPE_OCTET_STRING, pkey->params.raw_priv.data, pkey->params.raw_priv.size, raw); if (ret < 0) gnutls_assert(); return ret; case GNUTLS_PK_GOST_01: case GNUTLS_PK_GOST_12_256: case GNUTLS_PK_GOST_12_512: if ((ret = asn1_create_element (_gnutls_get_gnutls_asn(), "GNUTLS.GOSTPrivateKey", &spk)) != ASN1_SUCCESS) { gnutls_assert(); ret = _gnutls_asn2err(ret); goto error; } ret = _gnutls_x509_write_key_int_le(spk, "", pkey->params.params[GOST_K]); if (ret < 0) { gnutls_assert(); goto error; } ret = _gnutls_x509_der_encode(spk, "", raw, 0); if (ret < 0) { gnutls_assert(); goto error; } asn1_delete_structure2(&spk, ASN1_DELETE_FLAG_ZEROIZE); break; case GNUTLS_PK_RSA: case GNUTLS_PK_RSA_PSS: case GNUTLS_PK_ECDSA: ret = _gnutls_x509_export_int2(pkey->key, GNUTLS_X509_FMT_DER, "", raw); if (ret < 0) { gnutls_assert(); goto error; } break; case GNUTLS_PK_DSA: /* DSAPublicKey == INTEGER */ if ((ret = asn1_create_element (_gnutls_get_gnutls_asn(), "GNUTLS.DSAPublicKey", &spk)) != ASN1_SUCCESS) { gnutls_assert(); return _gnutls_asn2err(ret); } ret = _gnutls_x509_write_int(spk, "", pkey->params.params[4], 1); if (ret < 0) { gnutls_assert(); goto error; } ret = _gnutls_x509_der_encode(spk, "", raw, 0); if (ret < 0) { gnutls_assert(); goto error; } asn1_delete_structure2(&spk, ASN1_DELETE_FLAG_ZEROIZE); break; default: gnutls_assert(); return GNUTLS_E_INVALID_REQUEST; } return 0; error: asn1_delete_structure2(&spk, ASN1_DELETE_FLAG_ZEROIZE); asn1_delete_structure(&spk); return ret; }
static int auth(smb_session *s, const char *domain, const char *user, const char *password) { smb_message *msg = NULL, resp; smb_session_xsec_req req; smb_buffer ntlm; ASN1_TYPE token; int res, der_size = 512; char der[512], err_desc[ASN1_MAX_ERROR_DESCRIPTION_SIZE]; msg = smb_message_new(SMB_CMD_SETUP); if (!msg) return DSM_ERROR_GENERIC; // this struct will be set at the end when we know the payload size SMB_MSG_ADVANCE_PKT(msg, smb_session_xsec_req); asn1_create_element(s->spnego_asn1, "SPNEGO.NegotiationToken", &token); // Select a response message type res = asn1_write_value(token, "", "negTokenResp", 1); if (res != ASN1_SUCCESS) goto error; // Delete all optionnal field except 'ResponseToken' res = asn1_write_value(token, "negTokenResp.negResult", NULL, 0); if (res != ASN1_SUCCESS) goto error; res = asn1_write_value(token, "negTokenResp.supportedMech", NULL, 0); if (res != ASN1_SUCCESS) goto error; res = asn1_write_value(token, "negTokenResp.mechListMIC", NULL, 0); if (res != ASN1_SUCCESS) goto error; smb_ntlmssp_response(s->srv.challenge, s->srv.ts - 4200, domain, domain, user, password, &s->xsec_target, &ntlm); res = asn1_write_value(token, "negTokenResp.responseToken", ntlm.data, ntlm.size); smb_buffer_free(&ntlm); if (res != ASN1_SUCCESS) goto error; res = asn1_der_coding(token, "", der, &der_size, err_desc); if (res != ASN1_SUCCESS) { smb_message_destroy(msg); BDSM_dbg("Encoding error: %s", err_desc); return DSM_ERROR_GENERIC; } smb_message_append(msg, der, der_size); if (msg->cursor % 2) smb_message_put8(msg, 0); smb_message_put_utf16(msg, SMB_OS, strlen(SMB_OS)); smb_message_put16(msg, 0); smb_message_put_utf16(msg, SMB_LANMAN, strlen(SMB_LANMAN)); smb_message_put16(msg, 0); smb_message_put16(msg, 0); // Empty PDC name SMB_MSG_INIT_PKT_ANDX(req); req.wct = 12; req.max_buffer = SMB_SESSION_MAX_BUFFER; req.mpx_count = 16; // XXX ? req.vc_count = 1; req.caps = s->srv.caps; // XXX caps & our_caps_mask req.session_key = s->srv.session_key; req.xsec_blob_size = der_size; req.payload_size = msg->cursor - sizeof(smb_session_xsec_req); SMB_MSG_INSERT_PKT(msg, 0, req); asn1_delete_structure(&token); if (!smb_session_send_msg(s, msg)) { smb_message_destroy(msg); BDSM_dbg("Unable to send Session Setup AndX (NTLMSSP_AUTH) message\n"); return DSM_ERROR_NETWORK; } smb_message_destroy(msg); if (smb_session_recv_msg(s, &resp) == 0) return DSM_ERROR_NETWORK; if (!smb_session_check_nt_status(s, &resp)) return DSM_ERROR_NT; else { smb_session_xsec_resp *r = (smb_session_xsec_resp *)resp.packet->payload; if (r->action & 0x0001) s->guest = true; s->srv.uid = resp.packet->header.uid; s->logged = true; return DSM_SUCCESS; } error: asn1_display_error("smb_session_login auth()", res); smb_message_destroy(msg); return DSM_ERROR_GENERIC; }
int _pkcs12_decode_crt_bag(gnutls_pkcs12_bag_type_t type, const gnutls_datum_t * in, gnutls_datum_t * out) { int ret; ASN1_TYPE c2 = ASN1_TYPE_EMPTY; switch (type) { case GNUTLS_BAG_CERTIFICATE: if ((ret = asn1_create_element(_gnutls_get_pkix(), "PKIX1.pkcs-12-CertBag", &c2)) != ASN1_SUCCESS) { gnutls_assert(); ret = _gnutls_asn2err(ret); goto cleanup; } ret = asn1_der_decoding(&c2, in->data, in->size, NULL); if (ret != ASN1_SUCCESS) { gnutls_assert(); ret = _gnutls_asn2err(ret); goto cleanup; } ret = _gnutls_x509_read_string(c2, "certValue", out, ASN1_ETYPE_OCTET_STRING, 1); if (ret < 0) { gnutls_assert(); goto cleanup; } break; case GNUTLS_BAG_CRL: if ((ret = asn1_create_element(_gnutls_get_pkix(), "PKIX1.pkcs-12-CRLBag", &c2)) != ASN1_SUCCESS) { gnutls_assert(); ret = _gnutls_asn2err(ret); goto cleanup; } ret = asn1_der_decoding(&c2, in->data, in->size, NULL); if (ret != ASN1_SUCCESS) { gnutls_assert(); ret = _gnutls_asn2err(ret); goto cleanup; } ret = _gnutls_x509_read_string(c2, "crlValue", out, ASN1_ETYPE_OCTET_STRING, 1); if (ret < 0) { gnutls_assert(); goto cleanup; } break; case GNUTLS_BAG_SECRET: if ((ret = asn1_create_element(_gnutls_get_pkix(), "PKIX1.pkcs-12-SecretBag", &c2)) != ASN1_SUCCESS) { gnutls_assert(); ret = _gnutls_asn2err(ret); goto cleanup; } ret = asn1_der_decoding(&c2, in->data, in->size, NULL); if (ret != ASN1_SUCCESS) { gnutls_assert(); ret = _gnutls_asn2err(ret); goto cleanup; } ret = _gnutls_x509_read_string(c2, "secretValue", out, ASN1_ETYPE_OCTET_STRING, 1); if (ret < 0) { gnutls_assert(); goto cleanup; } break; default: gnutls_assert(); asn1_delete_structure(&c2); return GNUTLS_E_UNIMPLEMENTED_FEATURE; } asn1_delete_structure(&c2); return 0; cleanup: asn1_delete_structure(&c2); return ret; }
/* Creates an empty signed data structure in the pkcs7 * structure and returns a handle to the signed data. */ static int create_empty_signed_data (ASN1_TYPE pkcs7, ASN1_TYPE * sdata) { uint8_t one = 1; int result; *sdata = ASN1_TYPE_EMPTY; if ((result = asn1_create_element (_gnutls_get_pkix (), "PKIX1.pkcs-7-SignedData", sdata)) != ASN1_SUCCESS) { gnutls_assert (); result = _gnutls_asn2err (result); goto cleanup; } /* Use version 1 */ result = asn1_write_value (*sdata, "version", &one, 1); if (result != ASN1_SUCCESS) { gnutls_assert (); result = _gnutls_asn2err (result); goto cleanup; } /* Use no digest algorithms */ /* id-data */ result = asn1_write_value (*sdata, "encapContentInfo.eContentType", "1.2.840.113549.1.7.5", 1); if (result != ASN1_SUCCESS) { gnutls_assert (); result = _gnutls_asn2err (result); goto cleanup; } result = asn1_write_value (*sdata, "encapContentInfo.eContent", NULL, 0); if (result != ASN1_SUCCESS) { gnutls_assert (); result = _gnutls_asn2err (result); goto cleanup; } /* Add no certificates. */ /* Add no crls. */ /* Add no signerInfos. */ /* Write the content type of the signed data */ result = asn1_write_value (pkcs7, "contentType", SIGNED_DATA_OID, 1); if (result != ASN1_SUCCESS) { gnutls_assert (); result = _gnutls_asn2err (result); goto cleanup; } return 0; cleanup: asn1_delete_structure (sdata); return result; }