@@ -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+ }
0 commit comments