diff options
Diffstat (limited to 'lib/x509/key_encode.c')
-rw-r--r-- | lib/x509/key_encode.c | 215 |
1 files changed, 215 insertions, 0 deletions
diff --git a/lib/x509/key_encode.c b/lib/x509/key_encode.c index 0f12975d18..6cd42f2c0f 100644 --- a/lib/x509/key_encode.c +++ b/lib/x509/key_encode.c @@ -39,6 +39,10 @@ static int _gnutls_x509_write_dsa_params(gnutls_pk_params_st * params, gnutls_datum_t * der); static int _gnutls_x509_write_dsa_pubkey(gnutls_pk_params_st * params, gnutls_datum_t * der); +static int _gnutls_x509_write_gost_params(gnutls_pk_params_st * params, + gnutls_datum_t * der); +static int _gnutls_x509_write_gost_pubkey(gnutls_pk_params_st * params, + gnutls_datum_t * der); /* * some x509 certificate functions that relate to MPI parameter @@ -157,6 +161,78 @@ _gnutls_x509_write_eddsa_pubkey(gnutls_pk_params_st * params, } int +_gnutls_x509_write_gost_pubkey(gnutls_pk_params_st * params, + gnutls_datum_t * der) +{ + bigint_t x, y; + int numlen; + int byte_size, ret; + size_t size; + int pos; + + der->data = NULL; + der->size = 0; + + if (params->params_nr < GOST_PUBLIC_PARAMS) + return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); + + x = params->params[GOST_X]; + y = params->params[GOST_Y]; + numlen = gnutls_ecc_curve_get_size(params->curve); + + if (numlen == 0) + return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); + + der->size = 1 + ASN1_MAX_LENGTH_SIZE + 2 * numlen; + + der->data = gnutls_malloc(der->size); + if (der->data == NULL) + return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); + + memset(der->data, 0, der->size); + + der->data[0] = ASN1_TAG_OCTET_STRING; + asn1_length_der(2 * numlen, &der->data[1], &pos); + pos += 1; + + /* pad and store x */ + byte_size = (_gnutls_mpi_get_nbits(x) + 7) / 8; + if (numlen < byte_size) { + ret = gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); + goto cleanup; + } + + size = numlen; + ret = _gnutls_mpi_print_le(x, &der->data[pos], &size); + if (ret < 0) { + gnutls_assert(); + goto cleanup; + } + + /* pad and store y */ + byte_size = (_gnutls_mpi_get_nbits(y) + 7) / 8; + if (numlen < byte_size) { + ret = gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); + goto cleanup; + } + + size = numlen; + ret = _gnutls_mpi_print_le(y, &der->data[pos + numlen], &size); + if (ret < 0) { + gnutls_assert(); + goto cleanup; + } + + der->size = pos + 2 * numlen; + + return 0; + + cleanup: + _gnutls_free_datum(der); + return ret; +} + +int _gnutls_x509_write_pubkey_params(gnutls_pk_params_st * params, gnutls_datum_t * der) { @@ -180,6 +256,10 @@ _gnutls_x509_write_pubkey_params(gnutls_pk_params_st * params, der->size = 0; return 0; + case GNUTLS_PK_GOST_01: + case GNUTLS_PK_GOST_12_256: + case GNUTLS_PK_GOST_12_512: + return _gnutls_x509_write_gost_params(params, der); default: return gnutls_assert_val(GNUTLS_E_UNIMPLEMENTED_FEATURE); } @@ -199,6 +279,10 @@ _gnutls_x509_write_pubkey(gnutls_pk_params_st * params, return _gnutls_x509_write_ecc_pubkey(params, der); case GNUTLS_PK_EDDSA_ED25519: return _gnutls_x509_write_eddsa_pubkey(params, der); + case GNUTLS_PK_GOST_01: + case GNUTLS_PK_GOST_12_256: + case GNUTLS_PK_GOST_12_512: + return _gnutls_x509_write_gost_pubkey(params, der); default: return gnutls_assert_val(GNUTLS_E_UNIMPLEMENTED_FEATURE); } @@ -439,6 +523,93 @@ _gnutls_x509_write_rsa_pss_params(gnutls_x509_spki_st *params, return result; } +static int +_gnutls_x509_write_gost_params(gnutls_pk_params_st * params, + gnutls_datum_t * der) +{ + int result; + ASN1_TYPE spk = ASN1_TYPE_EMPTY; + const char *oid; + + der->data = NULL; + der->size = 0; + + oid = gnutls_ecc_curve_get_oid(params->curve); + if (oid == NULL) + return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); + + + if ((result = asn1_create_element + (_gnutls_get_gnutls_asn(), "GNUTLS.GOSTParameters", &spk)) + != ASN1_SUCCESS) { + gnutls_assert(); + return _gnutls_asn2err(result); + } + + if ((result = + asn1_write_value(spk, "publicKeyParamSet", oid, + 1)) != ASN1_SUCCESS) { + gnutls_assert(); + result = _gnutls_asn2err(result); + goto cleanup; + } + + if (params->algo == GNUTLS_PK_GOST_01) + oid = HASH_OID_GOST_R_3411_94_CRYPTOPRO_PARAMS; + else if (params->algo == GNUTLS_PK_GOST_12_256) + oid = HASH_OID_STREEBOG_256; + else if (params->algo == GNUTLS_PK_GOST_12_512) + oid = HASH_OID_STREEBOG_512; + else { + gnutls_assert(); + result = GNUTLS_E_INVALID_REQUEST; + goto cleanup; + } + + if ((result = + asn1_write_value(spk, "digestParamSet", oid, + 1)) != ASN1_SUCCESS) { + gnutls_assert(); + result = _gnutls_asn2err(result); + goto cleanup; + } + + oid = gnutls_gost_paramset_get_oid(params->gost_params); + if (oid == NULL) { + gnutls_assert(); + result = GNUTLS_E_INVALID_REQUEST; + goto cleanup; + } + + if (params->algo == GNUTLS_PK_GOST_01) { + if (params->gost_params == GNUTLS_GOST_PARAMSET_CP_A) + oid = NULL; + } else { + if (params->gost_params == GNUTLS_GOST_PARAMSET_TC26_Z) + oid = NULL; + } + + if ((result = + asn1_write_value(spk, "encryptionParamSet", oid, + oid ? 1 : 0)) != ASN1_SUCCESS) { + gnutls_assert(); + result = _gnutls_asn2err(result); + goto cleanup; + } + + result = _gnutls_x509_der_encode(spk, "", der, 0); + if (result < 0) { + gnutls_assert(); + goto cleanup; + } + + result = 0; + + cleanup: + asn1_delete_structure(&spk); + return result; +} + /* * This function writes the public parameters for DSS keys. * Needs 1 parameter (y). @@ -729,6 +900,46 @@ cleanup: return ret; } +static int +_gnutls_asn1_encode_gost(ASN1_TYPE * c2, gnutls_pk_params_st * params) +{ + int ret; + const char *oid; + + oid = gnutls_pk_get_oid(params->algo); + + if (params->params_nr != GOST_PRIVATE_PARAMS || oid == NULL) + return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); + + /* first make sure that no previously allocated data are leaked */ + if (*c2 != ASN1_TYPE_EMPTY) { + asn1_delete_structure(c2); + *c2 = ASN1_TYPE_EMPTY; + } + + if ((ret = asn1_create_element + (_gnutls_get_gnutls_asn(), "GNUTLS.GOSTPrivateKey", c2)) + != ASN1_SUCCESS) { + gnutls_assert(); + ret = _gnutls_asn2err(ret); + goto cleanup; + } + + ret = + _gnutls_x509_write_key_int_le(*c2, "", params->params[GOST_K]); + if (ret < 0) { + gnutls_assert(); + goto cleanup; + } + + + return 0; + +cleanup: + asn1_delete_structure2(c2, ASN1_DELETE_FLAG_ZEROIZE); + + return ret; +} /* Encodes the DSA parameters into an ASN.1 DSAPrivateKey structure. */ @@ -820,6 +1031,10 @@ int _gnutls_asn1_encode_privkey(ASN1_TYPE * c2, case GNUTLS_PK_ECDSA: case GNUTLS_PK_EDDSA_ED25519: return _gnutls_asn1_encode_ecc(c2, params); + case GNUTLS_PK_GOST_01: + case GNUTLS_PK_GOST_12_256: + case GNUTLS_PK_GOST_12_512: + return _gnutls_asn1_encode_gost(c2, params); default: return GNUTLS_E_UNIMPLEMENTED_FEATURE; } |