return ret;
}
+static int gost_set_raw_pub_key(EVP_PKEY *pk, const unsigned char *pub, size_t len)
+{
+ int ret = 0;
+ BIGNUM *X = NULL;
+ BIGNUM *Y = NULL;
+ EC_POINT *pub_key = NULL;
+ EC_KEY *ec;
+ const EC_GROUP *group;
+ const BIGNUM *order;
+ int half;
+
+ if (pub == NULL || len == 0) {
+ return 0;
+ }
+
+ if ((ec = EVP_PKEY_get0(pk)) == NULL
+ || (group = EC_KEY_get0_group(ec)) == NULL
+ || (order = EC_GROUP_get0_order(group)) == NULL) {
+ return 0;
+ }
+
+ half = len / 2;
+ if ((X = BN_lebin2bn(pub, half, NULL)) == NULL
+ || (Y = BN_lebin2bn(pub + half, half, NULL)) == NULL
+ || (pub_key = EC_POINT_new(group)) == NULL) {
+ goto end;
+ }
+
+ if (EC_POINT_set_affine_coordinates(group, pub_key, X, Y, NULL) != 1) {
+ goto end;
+ }
+
+ if (EC_KEY_set_public_key(ec, pub_key) != 1) {
+ goto end;
+ }
+
+ ret = 1;
+end:
+ EC_POINT_free(pub_key);
+ BN_free(Y);
+ BN_free(X);
+ return ret;
+}
+
+static int gost_get_raw_priv_key(const EVP_PKEY *pk, unsigned char *priv, size_t *len)
+{
+ const EC_KEY *ec;
+ const EC_GROUP *group;
+ const BIGNUM *order;
+ const BIGNUM *priv_key;
+ int half;
+
+ if (len == NULL) {
+ return 0;
+ }
+
+ if ((ec = EVP_PKEY_get0(pk)) == NULL
+ || (group = EC_KEY_get0_group(ec)) == NULL
+ || (order = EC_GROUP_get0_order(group)) == NULL
+ || (priv_key = EC_KEY_get0_private_key(ec)) == NULL) {
+ return 0;
+ }
+
+ half = BN_num_bytes(order);
+ if (priv == NULL) {
+ *len = half;
+ return 1;
+ }
+
+ if (BN_bn2lebinpad(priv_key, priv, half) != half) {
+ return 0;
+ }
+
+ return 1;
+}
+
+static int gost_get_raw_pub_key(const EVP_PKEY *pk, unsigned char *pub, size_t *len)
+{
+ int ret = 0;
+ BIGNUM *X = NULL;
+ BIGNUM *Y = NULL;
+ const EC_KEY *ec;
+ const EC_GROUP *group;
+ const BIGNUM *order;
+ const EC_POINT *pub_key;
+ int half;
+
+ if (len == NULL) {
+ return 0;
+ }
+
+ if ((ec = EVP_PKEY_get0(pk)) == NULL
+ || (group = EC_KEY_get0_group(ec)) == NULL
+ || (order = EC_GROUP_get0_order(group)) == NULL
+ || (pub_key = EC_KEY_get0_public_key(ec)) == NULL) {
+ return 0;
+ }
+
+ half = BN_num_bytes(order);
+ if (pub == NULL) {
+ *len = 2 * half;
+ return 1;
+ }
+
+ if (*len < 2 * half) {
+ return 0;
+ }
+
+ if ((X = BN_new()) == NULL
+ || (Y = BN_new()) == NULL) {
+ goto end;
+ }
+
+ if (EC_POINT_get_affine_coordinates(group, pub_key, X, Y, NULL) != 1) {
+ goto end;
+ }
+
+ if (BN_bn2lebinpad(X, pub, half) != half
+ || BN_bn2lebinpad(Y, pub + half, half) != half) {
+ goto end;
+ }
+
+ ret = 1;
+ end:
+ BN_free(Y);
+ BN_free(X);
+ return ret;
+}
+
/*
* Control function
*/
case ASN1_PKEY_CTRL_DEFAULT_MD_NID:
*(int *)arg2 = md_nid;
return 2;
+ case ASN1_PKEY_CTRL_GET1_TLS_ENCPT:
+ {
+ unsigned char **dup = (unsigned char **)arg2;
+ unsigned char *buf = NULL;
+ size_t len;
+
+ if (dup == NULL
+ || gost_get_raw_pub_key(pkey, NULL, &len) != 1
+ || (buf = OPENSSL_malloc(len)) == NULL
+ || gost_get_raw_pub_key(pkey, buf, &len) != 1) {
+ if (buf)
+ OPENSSL_free(buf);
+ return 0;
+ }
+
+ *dup = buf;
+ return len;
+ }
+ case ASN1_PKEY_CTRL_SET1_TLS_ENCPT:
+ return gost_set_raw_pub_key(pkey, (const unsigned char *)arg2, arg1);
}
return -2;
pub_cmp_gost_ec, pub_print_gost_ec,
pkey_size_gost, pkey_bits_gost);
+ EVP_PKEY_asn1_set_set_pub_key(*ameth, gost_set_raw_pub_key);
+ EVP_PKEY_asn1_set_get_priv_key(*ameth, gost_get_raw_priv_key);
+ EVP_PKEY_asn1_set_get_pub_key(*ameth, gost_get_raw_pub_key);
+
EVP_PKEY_asn1_set_ctrl(*ameth, pkey_ctrl_gost);
EVP_PKEY_asn1_set_security_bits(*ameth, pkey_bits_gost);
break;
EVP_PKEY_CTX_free(ctx1);
EVP_PKEY_free(key1);
+ /* Extract public key in raw format.
+ * Should contain X||Y in little endian.
+ */
+ size_t publen;
+ unsigned char *pub;
+ err = EVP_PKEY_get_raw_public_key(priv_key, NULL, &publen);
+ T(pub = OPENSSL_zalloc(publen));
+ err &= EVP_PKEY_get_raw_public_key(priv_key, pub, &publen);
+ printf("\tEVP_PKEY_get_raw_public_key:");
+ print_test_tf(err, err, "success", "failure");
+ ret |= err != 1;
+
+ unsigned char *pub2 = NULL;
+ int pub2len = EVP_PKEY_get1_encoded_public_key(priv_key, &pub2);
+ err = (publen == pub2len) && pub2 && !memcmp(pub, pub2, publen);
+ printf("\tEVP_PKEY_get1_encoded_public_key:\t");
+ print_test_tf(err, err, "success", "failure");
+ ret |= err != 1;
+ if (pub2)
+ OPENSSL_free(pub2);
+
+ EVP_PKEY *copy_key;
+ T(copy_key = EVP_PKEY_new());
+ T(EVP_PKEY_copy_parameters(copy_key, priv_key));
+ err = EVP_PKEY_set1_encoded_public_key(copy_key, pub, publen);
+ printf("\tEVP_PKEY_set1_encoded_public_key:\t");
+ print_test_tf(err, err, "success", "failure");
+ EVP_PKEY_free(copy_key);
+ OPENSSL_free(pub);
+ ret |= err != 1;
+
+ /* Extract private key in raw format.
+ * Should contain d on little endian form.
+ */
+ size_t privlen;
+ unsigned char *priv;
+ err = EVP_PKEY_get_raw_private_key(priv_key, NULL, &privlen);
+ T(priv = OPENSSL_zalloc(privlen));
+ err &= EVP_PKEY_get_raw_private_key(priv_key, priv, &privlen);
+ printf("\tEVP_PKEY_get_raw_private_key:\t");
+ print_test_tf(err, err, "success", "failure");
+ OPENSSL_free(priv);
+ ret |= err != 1;
+
/*
* Prepare for sign testing.
*/