static int x25519_keycheck(const EC_KEY *eckey) { const char *pubkey; if (eckey->pub_key == NULL) return 0; pubkey = eckey->pub_key->custom_data; if (pubkey == NULL) return 0; if (eckey->custom_data != NULL) { uint8_t tmp[EC_X25519_KEYLEN]; /* Check eckey->priv_key exists and matches eckey->custom_data */ if (eckey->priv_key == NULL) return 0; if (BN_bn2lebinpad(eckey->priv_key, tmp, EC_X25519_KEYLEN) != EC_X25519_KEYLEN || CRYPTO_memcmp(tmp, eckey->custom_data, EC_X25519_KEYLEN) != 0) { OPENSSL_cleanse(tmp, EC_X25519_KEYLEN); return 0; } X25519_public_from_private(tmp, eckey->custom_data); if (CRYPTO_memcmp(pubkey, tmp, EC_X25519_KEYLEN) == 0) return 1; return 0; } else { return 1; } }
/* Setup EVP_PKEY using public, private or generation */ static int ecx_key_op(EVP_PKEY *pkey, int id, const X509_ALGOR *palg, const unsigned char *p, int plen, ecx_key_op_t op) { ECX_KEY *key = NULL; unsigned char *privkey, *pubkey; if (op != KEY_OP_KEYGEN) { if (palg != NULL) { int ptype; /* Algorithm parameters must be absent */ X509_ALGOR_get0(NULL, &ptype, NULL, palg); if (ptype != V_ASN1_UNDEF) { ECerr(EC_F_ECX_KEY_OP, EC_R_INVALID_ENCODING); return 0; } } if (p == NULL || plen != KEYLENID(id)) { ECerr(EC_F_ECX_KEY_OP, EC_R_INVALID_ENCODING); return 0; } } key = OPENSSL_zalloc(sizeof(*key)); if (key == NULL) { ECerr(EC_F_ECX_KEY_OP, ERR_R_MALLOC_FAILURE); return 0; } pubkey = key->pubkey; if (op == KEY_OP_PUBLIC) { memcpy(pubkey, p, plen); } else { privkey = key->privkey = OPENSSL_secure_malloc(KEYLENID(id)); if (privkey == NULL) { ECerr(EC_F_ECX_KEY_OP, ERR_R_MALLOC_FAILURE); goto err; } if (op == KEY_OP_KEYGEN) { if (RAND_priv_bytes(privkey, KEYLENID(id)) <= 0) { OPENSSL_secure_free(privkey); key->privkey = NULL; goto err; } if (id == EVP_PKEY_X25519) { privkey[0] &= 248; privkey[X25519_KEYLEN - 1] &= 127; privkey[X25519_KEYLEN - 1] |= 64; } else if (id == EVP_PKEY_X448) { privkey[0] &= 252; privkey[X448_KEYLEN - 1] |= 128; } } else { memcpy(privkey, p, KEYLENID(id)); } switch (id) { case EVP_PKEY_X25519: X25519_public_from_private(pubkey, privkey); break; case EVP_PKEY_ED25519: ED25519_public_from_private(pubkey, privkey); break; case EVP_PKEY_X448: X448_public_from_private(pubkey, privkey); break; case EVP_PKEY_ED448: ED448_public_from_private(pubkey, privkey); break; } } EVP_PKEY_assign(pkey, id, key); return 1; err: OPENSSL_free(key); return 0; }
static int x25519_keygenpub(EC_KEY *eckey) { X25519_public_from_private(eckey->pub_key->custom_data, eckey->custom_data); return 1; }