/** * gnutls_x509_rdn_get: * @idn: should contain a DER encoded RDN sequence * @buf: a pointer to a structure to hold the peer's name * @buf_size: holds the size of @buf * * This function will return the name of the given RDN sequence. The * name will be in the form "C=xxxx,O=yyyy,CN=zzzz" as described in * RFC4514. * * This function does not output a fully RFC4514 compliant string, if * that is required see gnutls_x509_rdn_get2(). * * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, or * %GNUTLS_E_SHORT_MEMORY_BUFFER is returned and *@buf_size is * updated if the provided buffer is not long enough, otherwise a * negative error value. **/ int gnutls_x509_rdn_get(const gnutls_datum_t * idn, char *buf, size_t * buf_size) { int result; ASN1_TYPE dn = ASN1_TYPE_EMPTY; if (buf_size == 0) { gnutls_assert(); return GNUTLS_E_INVALID_REQUEST; } if (buf) buf[0] = 0; if ((result = asn1_create_element(_gnutls_get_pkix(), "PKIX1.Name", &dn)) != ASN1_SUCCESS) { gnutls_assert(); return _gnutls_asn2err(result); } result = _asn1_strict_der_decode(&dn, idn->data, idn->size, NULL); if (result != ASN1_SUCCESS) { /* couldn't decode DER */ gnutls_assert(); asn1_delete_structure(&dn); return _gnutls_asn2err(result); } result = _gnutls_x509_parse_dn(dn, "rdnSequence", buf, buf_size, GNUTLS_X509_DN_FLAG_COMPAT); asn1_delete_structure(&dn); 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; }
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; }
/* 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; }
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; }
int _gnutls_read_pbkdf1_params(const uint8_t * data, int data_size, struct pbkdf2_params *kdf_params, struct pbe_enc_params *enc_params) { ASN1_TYPE pasn = ASN1_TYPE_EMPTY; int len; int ret, result; memset(kdf_params, 0, sizeof(*kdf_params)); memset(enc_params, 0, sizeof(*enc_params)); if ((result = asn1_create_element(_gnutls_get_pkix(), "PKIX1.pkcs-5-PBE-params", &pasn)) != ASN1_SUCCESS) { gnutls_assert(); return _gnutls_asn2err(result); } /* Decode the parameters. */ result = _asn1_strict_der_decode(&pasn, data, data_size, NULL); if (result != ASN1_SUCCESS) { gnutls_assert(); ret = _gnutls_asn2err(result); goto error; } ret = _gnutls_x509_read_uint(pasn, "iterationCount", &kdf_params->iter_count); if (ret < 0) { gnutls_assert(); goto error; } if (kdf_params->iter_count >= MAX_ITER_COUNT || kdf_params->iter_count == 0) { ret = gnutls_assert_val(GNUTLS_E_ILLEGAL_PARAMETER); goto error; } len = sizeof(kdf_params->salt); result = asn1_read_value(pasn, "salt", kdf_params->salt, &len); if (result != ASN1_SUCCESS) { gnutls_assert(); ret = _gnutls_asn2err(result); goto error; } if (len != 8) { gnutls_assert(); ret = GNUTLS_E_ILLEGAL_PARAMETER; goto error; } enc_params->cipher = GNUTLS_CIPHER_DES_CBC; ret = 0; error: asn1_delete_structure2(&pasn, ASN1_DELETE_FLAG_ZEROIZE); return ret; }