Skip to content

Commit b289bd6

Browse files
committed
Merge branch 'delocator-peg-msl' of github.com:jakemas/aws-lc into delocator-peg-msl
2 parents 6df1307 + f45cf24 commit b289bd6

File tree

20 files changed

+868
-239
lines changed

20 files changed

+868
-239
lines changed

crypto/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -418,6 +418,7 @@ add_library(
418418
evp_extra/p_dsa.c
419419
evp_extra/p_dsa_asn1.c
420420
evp_extra/p_ec_asn1.c
421+
evp_extra/p_ed25519ph.c
421422
evp_extra/p_ed25519_asn1.c
422423
evp_extra/p_hmac_asn1.c
423424
evp_extra/p_kem_asn1.c

crypto/evp_extra/evp_test.cc

Lines changed: 277 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1529,3 +1529,280 @@ TEST(EVPTest, PKEY_asn1_find_str) {
15291529
ASSERT_FALSE(ameth);
15301530
ASSERT_FALSE(EVP_PKEY_asn1_get0_info(&pkey_id, &pkey_base_id, &pkey_flags, &pinfo, &pem_str, ameth));
15311531
}
1532+
1533+
TEST(EVPTest, ED25519PH) {
1534+
const uint8_t message[] = {0x72, 0x61, 0x63, 0x63, 0x6f, 0x6f, 0x6e};
1535+
const uint8_t context[] = {0x73, 0x6e, 0x65, 0x61, 0x6b, 0x79};
1536+
const uint8_t message_sha512[] = {
1537+
0x50, 0xcf, 0x03, 0x79, 0x8c, 0xb2, 0xfb, 0x0f, 0xf1, 0x3d, 0xc6,
1538+
0x4c, 0x7c, 0xf0, 0x89, 0x8f, 0xfe, 0x90, 0x9d, 0xfd, 0xa5, 0x22,
1539+
0xdd, 0x22, 0xf4, 0x10, 0x8f, 0xa0, 0x1b, 0x8f, 0x29, 0x15, 0x98,
1540+
0x60, 0xf2, 0x80, 0x0e, 0x7c, 0x93, 0x3c, 0x7c, 0x6e, 0x4c, 0xb1,
1541+
0xf9, 0x3f, 0x33, 0xbe, 0x43, 0xa3, 0xd4, 0x1c, 0x86, 0x92, 0x2b,
1542+
0x32, 0xaf, 0x89, 0xa2, 0xa4, 0xa3, 0xe2, 0xf1, 0x92};
1543+
1544+
bssl::UniquePtr<EVP_PKEY> pkey(nullptr);
1545+
bssl::UniquePtr<EVP_PKEY> pubkey(nullptr);
1546+
bssl::ScopedCBB marshalled_private_key;
1547+
bssl::ScopedCBB marshalled_public_key;
1548+
uint8_t signature[ED25519_SIGNATURE_LEN] = {0};
1549+
size_t signature_len = ED25519_SIGNATURE_LEN;
1550+
uint8_t working_signature[ED25519_SIGNATURE_LEN] = {0};
1551+
size_t working_signature_len = ED25519_SIGNATURE_LEN;
1552+
1553+
{
1554+
bssl::UniquePtr<EVP_PKEY_CTX> ctx(
1555+
EVP_PKEY_CTX_new_id(EVP_PKEY_ED25519PH, nullptr));
1556+
ASSERT_FALSE(EVP_PKEY_keygen_init(ctx.get()));
1557+
}
1558+
1559+
{
1560+
bssl::UniquePtr<EVP_PKEY_CTX> ctx(
1561+
EVP_PKEY_CTX_new_id(EVP_PKEY_ED25519, nullptr));
1562+
ASSERT_TRUE(EVP_PKEY_keygen_init(ctx.get()));
1563+
EVP_PKEY *pkey_ptr = nullptr;
1564+
ASSERT_TRUE(EVP_PKEY_keygen(ctx.get(), &pkey_ptr));
1565+
ASSERT_NE(pkey_ptr, nullptr);
1566+
pkey.reset(pkey_ptr); // now owns pkey_ptr
1567+
// marshal the keys
1568+
ASSERT_TRUE(CBB_init(marshalled_private_key.get(), 0));
1569+
ASSERT_TRUE(CBB_init(marshalled_public_key.get(), 0));
1570+
ASSERT_TRUE(
1571+
EVP_marshal_private_key(marshalled_private_key.get(), pkey.get()));
1572+
ASSERT_TRUE(
1573+
EVP_marshal_public_key(marshalled_public_key.get(), pkey.get()));
1574+
}
1575+
1576+
{
1577+
uint8_t raw_key[ED25519_PRIVATE_KEY_SEED_LEN];
1578+
size_t raw_key_len = sizeof(raw_key);
1579+
ASSERT_TRUE(EVP_PKEY_get_raw_private_key(pkey.get(), raw_key, &raw_key_len));
1580+
1581+
EVP_PKEY *rk = EVP_PKEY_new_raw_private_key(EVP_PKEY_ED25519PH, nullptr, raw_key, raw_key_len);
1582+
ASSERT_TRUE(rk);
1583+
pkey.reset(rk);
1584+
ASSERT_EQ(EVP_PKEY_ED25519PH, EVP_PKEY_id(pkey.get()));
1585+
1586+
bssl::ScopedCBB temp;
1587+
ASSERT_TRUE(CBB_init(temp.get(), 0));
1588+
ASSERT_FALSE(EVP_marshal_private_key(temp.get(), pkey.get()));
1589+
}
1590+
1591+
{
1592+
uint8_t raw_key[ED25519_PUBLIC_KEY_LEN];
1593+
size_t raw_key_len = sizeof(raw_key);
1594+
ASSERT_TRUE(EVP_PKEY_get_raw_public_key(pkey.get(), raw_key, &raw_key_len));
1595+
1596+
EVP_PKEY *rk = EVP_PKEY_new_raw_public_key(EVP_PKEY_ED25519PH, nullptr, raw_key, raw_key_len);
1597+
ASSERT_TRUE(rk);
1598+
pubkey.reset(rk);
1599+
ASSERT_EQ(EVP_PKEY_ED25519PH, EVP_PKEY_id(pubkey.get()));
1600+
1601+
bssl::ScopedCBB temp;
1602+
ASSERT_TRUE(CBB_init(temp.get(), 0));
1603+
ASSERT_FALSE(EVP_marshal_public_key(temp.get(), pubkey.get()));
1604+
}
1605+
1606+
// prehash signature w/ context gen and verify
1607+
{
1608+
bssl::UniquePtr<EVP_MD_CTX> md_ctx(EVP_MD_CTX_new());
1609+
EVP_PKEY_CTX *pctx = nullptr;
1610+
1611+
ASSERT_TRUE(EVP_DigestSignInit(md_ctx.get(), &pctx, EVP_sha512(), nullptr,
1612+
pkey.get()));
1613+
1614+
ASSERT_TRUE(
1615+
EVP_PKEY_CTX_set_signature_context(pctx, context, sizeof(context)));
1616+
const uint8_t *sctx = NULL;
1617+
size_t sctx_len = 0;
1618+
ASSERT_TRUE(EVP_PKEY_CTX_get0_signature_context(pctx, &sctx, &sctx_len));
1619+
ASSERT_TRUE(sctx);
1620+
ASSERT_NE(sctx, context);
1621+
ASSERT_EQ(Bytes(context, sizeof(context)), Bytes(sctx, sctx_len));
1622+
1623+
ASSERT_TRUE(EVP_DigestSignUpdate(md_ctx.get(), &message[0], 3));
1624+
ASSERT_TRUE(
1625+
EVP_DigestSignUpdate(md_ctx.get(), &message[3], sizeof(message) - 3));
1626+
ASSERT_TRUE(EVP_DigestSignFinal(md_ctx.get(), signature,
1627+
&signature_len));
1628+
ASSERT_EQ(signature_len, (size_t)ED25519_SIGNATURE_LEN);
1629+
1630+
ASSERT_TRUE(EVP_DigestVerifyInit(md_ctx.get(), &pctx, EVP_sha512(), nullptr,
1631+
pubkey.get()));
1632+
ASSERT_TRUE(
1633+
EVP_PKEY_CTX_set_signature_context(pctx, context, sizeof(context)));
1634+
ASSERT_TRUE(EVP_DigestVerifyUpdate(md_ctx.get(), &message[0], 3));
1635+
ASSERT_TRUE(
1636+
EVP_DigestVerifyUpdate(md_ctx.get(), &message[3], sizeof(message) - 3));
1637+
ASSERT_TRUE(EVP_DigestVerifyFinal(md_ctx.get(),
1638+
signature, signature_len));
1639+
}
1640+
1641+
// prehash signature gen and verify w/ context using EVP_PKEY_sign and
1642+
// EVP_PKEY_verify directly
1643+
{
1644+
bssl::UniquePtr<EVP_PKEY_CTX> ctx(EVP_PKEY_CTX_new(pkey.get(), nullptr));
1645+
ASSERT_TRUE(ctx.get());
1646+
ASSERT_TRUE(EVP_PKEY_sign_init(ctx.get()));
1647+
ASSERT_TRUE(EVP_PKEY_CTX_set_signature_context(ctx.get(), context,
1648+
sizeof(context)));
1649+
ASSERT_TRUE(EVP_PKEY_sign(ctx.get(), working_signature, &working_signature_len, message_sha512, sizeof(message_sha512)));
1650+
ASSERT_EQ(working_signature_len, (size_t)ED25519_SIGNATURE_LEN);
1651+
1652+
ctx.reset(EVP_PKEY_CTX_new(pubkey.get(), nullptr));
1653+
ASSERT_TRUE(ctx.get());
1654+
ASSERT_TRUE(EVP_PKEY_verify_init(ctx.get()));
1655+
ASSERT_TRUE(EVP_PKEY_CTX_set_signature_context(ctx.get(), context,
1656+
sizeof(context)));
1657+
ASSERT_TRUE(EVP_PKEY_verify(ctx.get(), working_signature,
1658+
working_signature_len, message_sha512,
1659+
sizeof(message_sha512)));
1660+
1661+
ASSERT_EQ(Bytes(signature, signature_len),
1662+
Bytes(working_signature, working_signature_len));
1663+
}
1664+
1665+
// prehash signature gen and verify
1666+
{
1667+
bssl::UniquePtr<EVP_MD_CTX> md_ctx(EVP_MD_CTX_new());
1668+
EVP_PKEY_CTX *pctx;
1669+
1670+
ASSERT_TRUE(EVP_DigestSignInit(md_ctx.get(), &pctx, EVP_sha512(), nullptr,
1671+
pkey.get()));
1672+
1673+
const uint8_t *sctx = NULL;
1674+
size_t sctx_len = 0;
1675+
ASSERT_TRUE(EVP_PKEY_CTX_get0_signature_context(pctx, &sctx, &sctx_len));
1676+
ASSERT_EQ(sctx, nullptr);
1677+
ASSERT_EQ(sctx_len, (size_t)0);
1678+
1679+
ASSERT_TRUE(EVP_DigestSignUpdate(md_ctx.get(), &message[0], 3));
1680+
ASSERT_TRUE(
1681+
EVP_DigestSignUpdate(md_ctx.get(), &message[3], sizeof(message) - 3));
1682+
ASSERT_TRUE(EVP_DigestSignFinal(md_ctx.get(), working_signature,
1683+
&working_signature_len));
1684+
ASSERT_EQ(working_signature_len, (size_t)ED25519_SIGNATURE_LEN);
1685+
1686+
ASSERT_TRUE(EVP_DigestVerifyInit(md_ctx.get(), nullptr, EVP_sha512(),
1687+
nullptr, pubkey.get()));
1688+
ASSERT_TRUE(EVP_DigestVerifyUpdate(md_ctx.get(), message, 3));
1689+
ASSERT_TRUE(
1690+
EVP_DigestVerifyUpdate(md_ctx.get(), &message[3], sizeof(message) - 3));
1691+
ASSERT_TRUE(EVP_DigestVerifyFinal(md_ctx.get(), working_signature,
1692+
working_signature_len));
1693+
}
1694+
1695+
// Pre-hash signature w/ context should not match Pre-hash signature w/o context
1696+
ASSERT_NE(Bytes(signature, signature_len),
1697+
Bytes(working_signature, working_signature_len));
1698+
1699+
1700+
// prehash signature gen and verify with EVP_PKEY_sign and EVP_PKEY_verify directly
1701+
{
1702+
OPENSSL_memcpy(signature, working_signature, working_signature_len);
1703+
signature_len = working_signature_len;
1704+
1705+
bssl::UniquePtr<EVP_PKEY_CTX> ctx(EVP_PKEY_CTX_new(pkey.get(), nullptr));
1706+
ASSERT_TRUE(ctx.get());
1707+
ASSERT_TRUE(EVP_PKEY_sign_init(ctx.get()));
1708+
ASSERT_TRUE(EVP_PKEY_sign(ctx.get(), working_signature, &working_signature_len, message_sha512, sizeof(message_sha512)));
1709+
ASSERT_EQ(working_signature_len, (size_t)ED25519_SIGNATURE_LEN);
1710+
1711+
ctx.reset(EVP_PKEY_CTX_new(pubkey.get(), nullptr));
1712+
ASSERT_TRUE(ctx.get());
1713+
ASSERT_TRUE(EVP_PKEY_verify_init(ctx.get()));
1714+
ASSERT_TRUE(EVP_PKEY_verify(ctx.get(), working_signature, working_signature_len, message_sha512, sizeof(message_sha512)));
1715+
1716+
ASSERT_EQ(Bytes(signature, signature_len),
1717+
Bytes(working_signature, working_signature_len));
1718+
}
1719+
1720+
1721+
{
1722+
CBS cbs;
1723+
CBS_init(&cbs, CBB_data(marshalled_private_key.get()),
1724+
CBB_len(marshalled_private_key.get()));
1725+
EVP_PKEY *parsed = EVP_parse_private_key(&cbs);
1726+
ASSERT_TRUE(parsed);
1727+
pkey.reset(parsed);
1728+
ASSERT_EQ(EVP_PKEY_ED25519, EVP_PKEY_id(pkey.get()));
1729+
}
1730+
1731+
{
1732+
CBS cbs;
1733+
CBS_init(&cbs, CBB_data(marshalled_public_key.get()),
1734+
CBB_len(marshalled_public_key.get()));
1735+
EVP_PKEY *parsed = EVP_parse_public_key(&cbs);
1736+
ASSERT_TRUE(parsed);
1737+
pubkey.reset(parsed);
1738+
ASSERT_EQ(EVP_PKEY_ED25519, EVP_PKEY_id(pubkey.get()));
1739+
}
1740+
1741+
// pure signature gen and verify
1742+
{
1743+
bssl::UniquePtr<EVP_MD_CTX> md_ctx(EVP_MD_CTX_new());
1744+
ASSERT_TRUE(EVP_DigestSignInit(md_ctx.get(), nullptr, nullptr, nullptr,
1745+
pkey.get()));
1746+
ASSERT_TRUE(EVP_DigestSign(md_ctx.get(), working_signature,
1747+
&working_signature_len, message, sizeof(message)));
1748+
ASSERT_EQ(working_signature_len, (size_t)ED25519_SIGNATURE_LEN);
1749+
1750+
ASSERT_TRUE(EVP_DigestVerifyInit(md_ctx.get(), nullptr, nullptr, nullptr,
1751+
pubkey.get()));
1752+
ASSERT_TRUE(EVP_DigestVerify(md_ctx.get(), working_signature,
1753+
working_signature_len, message, sizeof(message)));
1754+
}
1755+
1756+
// pure signature shouldn't match a pre-hash signature w/o context
1757+
ASSERT_NE(Bytes(signature, signature_len),
1758+
Bytes(working_signature, working_signature_len));
1759+
}
1760+
1761+
TEST(EVPTest, Ed25519phTestVectors) {
1762+
FileTestGTest("crypto/fipsmodule/curve25519/ed25519ph_tests.txt", [](FileTest *t) {
1763+
std::vector<uint8_t> seed, q, message, context, expected_signature;
1764+
ASSERT_TRUE(t->GetBytes(&seed, "SEED"));
1765+
ASSERT_EQ(32u, seed.size());
1766+
ASSERT_TRUE(t->GetBytes(&q, "Q"));
1767+
ASSERT_EQ(32u, q.size());
1768+
ASSERT_TRUE(t->GetBytes(&message, "MESSAGE"));
1769+
ASSERT_TRUE(t->GetBytes(&expected_signature, "SIGNATURE"));
1770+
ASSERT_EQ(64u, expected_signature.size());
1771+
1772+
if (t->HasAttribute("CONTEXT")) {
1773+
t->GetBytes(&context, "CONTEXT");
1774+
} else {
1775+
context = std::vector<uint8_t>();
1776+
}
1777+
1778+
bssl::UniquePtr<EVP_PKEY> pkey(EVP_PKEY_new_raw_private_key(EVP_PKEY_ED25519PH, nullptr, seed.data(), seed.size()));
1779+
bssl::UniquePtr<EVP_PKEY> pubkey(EVP_PKEY_new_raw_public_key(EVP_PKEY_ED25519PH, nullptr, q.data(), q.size()));
1780+
ASSERT_TRUE(pkey.get());
1781+
ASSERT_TRUE(pubkey.get());
1782+
ASSERT_EQ(EVP_PKEY_ED25519PH, EVP_PKEY_id(pkey.get()));
1783+
ASSERT_EQ(EVP_PKEY_ED25519PH, EVP_PKEY_id(pubkey.get()));
1784+
1785+
bssl::UniquePtr<EVP_MD_CTX> md_ctx(EVP_MD_CTX_new());
1786+
EVP_PKEY_CTX *pctx = nullptr;
1787+
uint8_t signature[ED25519_SIGNATURE_LEN] = {};
1788+
size_t signature_len = ED25519_SIGNATURE_LEN;
1789+
1790+
ASSERT_TRUE(EVP_DigestSignInit(md_ctx.get(), &pctx, EVP_sha512(), nullptr,
1791+
pkey.get()));
1792+
ASSERT_TRUE(
1793+
EVP_PKEY_CTX_set_signature_context(pctx, context.data(), context.size()));
1794+
ASSERT_TRUE(EVP_DigestSignUpdate(md_ctx.get(), message.data(), message.size()));
1795+
ASSERT_TRUE(EVP_DigestSignFinal(md_ctx.get(), signature,
1796+
&signature_len));
1797+
ASSERT_EQ(signature_len, (size_t)ED25519_SIGNATURE_LEN);
1798+
ASSERT_EQ(Bytes(expected_signature), Bytes(signature, signature_len));
1799+
1800+
ASSERT_TRUE(EVP_DigestVerifyInit(md_ctx.get(), &pctx, EVP_sha512(), nullptr,
1801+
pubkey.get()));
1802+
ASSERT_TRUE(
1803+
EVP_PKEY_CTX_set_signature_context(pctx, context.data(), context.size()));
1804+
ASSERT_TRUE(EVP_DigestVerifyUpdate(md_ctx.get(), message.data(), message.size()));
1805+
ASSERT_TRUE(EVP_DigestVerifyFinal(md_ctx.get(), signature,
1806+
signature_len));
1807+
});
1808+
}

crypto/evp_extra/internal.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111

1212
#define PKCS8_VERSION_ONE 0
1313
#define PKCS8_VERSION_TWO 1
14-
#define ED25519_PUBLIC_KEY_OFFSET 32
1514

1615
typedef struct {
1716
uint8_t pub[32];
@@ -31,13 +30,15 @@ extern const EVP_PKEY_ASN1_METHOD pqdsa_asn1_meth;
3130
extern const EVP_PKEY_ASN1_METHOD kem_asn1_meth;
3231
extern const EVP_PKEY_ASN1_METHOD hmac_asn1_meth;
3332
extern const EVP_PKEY_ASN1_METHOD dh_asn1_meth;
33+
extern const EVP_PKEY_ASN1_METHOD ed25519ph_asn1_meth;
3434

3535
extern const EVP_PKEY_METHOD x25519_pkey_meth;
3636
extern const EVP_PKEY_METHOD hkdf_pkey_meth;
3737
extern const EVP_PKEY_METHOD hmac_pkey_meth;
3838
extern const EVP_PKEY_METHOD dh_pkey_meth;
3939
extern const EVP_PKEY_METHOD dsa_pkey_meth;
4040
extern const EVP_PKEY_METHOD pqdsa_pkey_meth;
41+
extern const EVP_PKEY_METHOD ed25519ph_pkey_meth;
4142

4243
// evp_pkey_set_method behaves like |EVP_PKEY_set_type|, but takes a pointer to
4344
// a method table. This avoids depending on every |EVP_PKEY_ASN1_METHOD|.

0 commit comments

Comments
 (0)