@@ -1425,4 +1425,213 @@ DataPointer pbkdf2(const EVP_MD* md,
14251425 return {};
14261426}
14271427
1428+ // ============================================================================
1429+
1430+ EVPKeyPointer EVPKeyPointer::New () {
1431+ return EVPKeyPointer (EVP_PKEY_new ());
1432+ }
1433+
1434+ EVPKeyPointer EVPKeyPointer::NewRawPublic (int id, const Buffer<const unsigned char >& data) {
1435+ if (id == 0 ) return {};
1436+ return EVPKeyPointer (EVP_PKEY_new_raw_public_key (id, nullptr , data.data , data.len ));
1437+ }
1438+
1439+ EVPKeyPointer EVPKeyPointer::NewRawPrivate (int id, const Buffer<const unsigned char >& data) {
1440+ if (id == 0 ) return {};
1441+ return EVPKeyPointer (EVP_PKEY_new_raw_private_key (id, nullptr , data.data , data.len ));
1442+ }
1443+
1444+ EVPKeyPointer::EVPKeyPointer (EVP_PKEY* pkey) : pkey_(pkey) {}
1445+
1446+ EVPKeyPointer::EVPKeyPointer (EVPKeyPointer&& other) noexcept
1447+ : pkey_(other.release()) {}
1448+
1449+ EVPKeyPointer& EVPKeyPointer::operator =(EVPKeyPointer&& other) noexcept {
1450+ if (this == &other) return *this ;
1451+ this ->~EVPKeyPointer ();
1452+ return *new (this ) EVPKeyPointer (std::move (other));
1453+ }
1454+
1455+ EVPKeyPointer::~EVPKeyPointer () { reset (); }
1456+
1457+ void EVPKeyPointer::reset (EVP_PKEY* pkey) {
1458+ pkey_.reset (pkey);
1459+ }
1460+
1461+ EVP_PKEY* EVPKeyPointer::release () {
1462+ return pkey_.release ();
1463+ }
1464+
1465+ int EVPKeyPointer::id (const EVP_PKEY* key) {
1466+ if (key == nullptr ) return 0 ;
1467+ return EVP_PKEY_id (key);
1468+ }
1469+
1470+ int EVPKeyPointer::base_id (const EVP_PKEY* key) {
1471+ if (key == nullptr ) return 0 ;
1472+ return EVP_PKEY_base_id (key);
1473+ }
1474+
1475+ int EVPKeyPointer::id () const {
1476+ return id (get ());
1477+ }
1478+
1479+ int EVPKeyPointer::base_id () const {
1480+ return base_id (get ());
1481+ }
1482+
1483+ int EVPKeyPointer::bits () const {
1484+ if (get () == nullptr ) return 0 ;
1485+ return EVP_PKEY_bits (get ());
1486+ }
1487+
1488+ size_t EVPKeyPointer::size () const {
1489+ if (get () == nullptr ) return 0 ;
1490+ return EVP_PKEY_size (get ());
1491+ }
1492+
1493+ EVPKeyCtxPointer EVPKeyPointer::newCtx () const {
1494+ if (!pkey_) return {};
1495+ return EVPKeyCtxPointer (EVP_PKEY_CTX_new (get (), nullptr ));
1496+ }
1497+
1498+ size_t EVPKeyPointer::rawPublicKeySize () const {
1499+ if (!pkey_) return 0 ;
1500+ size_t len = 0 ;
1501+ if (EVP_PKEY_get_raw_public_key (get (), nullptr , &len) == 1 ) return len;
1502+ return 0 ;
1503+ }
1504+
1505+ size_t EVPKeyPointer::rawPrivateKeySize () const {
1506+ if (!pkey_) return 0 ;
1507+ size_t len = 0 ;
1508+ if (EVP_PKEY_get_raw_private_key (get (), nullptr , &len) == 1 ) return len;
1509+ return 0 ;
1510+ }
1511+
1512+ DataPointer EVPKeyPointer::rawPublicKey () const {
1513+ if (!pkey_) return {};
1514+ if (auto data = DataPointer::Alloc (rawPublicKeySize ())) {
1515+ const Buffer<unsigned char > buf = data;
1516+ size_t len = data.size ();
1517+ if (EVP_PKEY_get_raw_public_key (get (),
1518+ buf.data ,
1519+ &len) != 1 ) return {};
1520+ return data;
1521+ }
1522+ return {};
1523+ }
1524+
1525+ DataPointer EVPKeyPointer::rawPrivateKey () const {
1526+ if (!pkey_) return {};
1527+ if (auto data = DataPointer::Alloc (rawPrivateKeySize ())) {
1528+ const Buffer<unsigned char > buf = data;
1529+ size_t len = data.size ();
1530+ if (EVP_PKEY_get_raw_private_key (get (),
1531+ buf.data ,
1532+ &len) != 1 ) return {};
1533+ return data;
1534+ }
1535+ return {};
1536+ }
1537+
1538+ BIOPointer EVPKeyPointer::derPublicKey () const {
1539+ if (!pkey_) return {};
1540+ auto bio = BIOPointer::NewMem ();
1541+ if (!bio) return {};
1542+ if (!i2d_PUBKEY_bio (bio.get (), get ())) return {};
1543+ return bio;
1544+ }
1545+
1546+ namespace {
1547+ EVPKeyPointer::ParseKeyResult TryParsePublicKeyInner (
1548+ const BIOPointer& bp,
1549+ const char * name,
1550+ auto && parse) {
1551+ if (!bp.resetBio ()) {
1552+ return EVPKeyPointer::ParseKeyResult (EVPKeyPointer::PKParseError::FAILED);
1553+ }
1554+ unsigned char * der_data;
1555+ long der_len;
1556+
1557+ // This skips surrounding data and decodes PEM to DER.
1558+ {
1559+ MarkPopErrorOnReturn mark_pop_error_on_return;
1560+ if (PEM_bytes_read_bio (&der_data, &der_len, nullptr , name,
1561+ bp.get (), nullptr , nullptr ) != 1 )
1562+ return EVPKeyPointer::ParseKeyResult (EVPKeyPointer::PKParseError::NOT_RECOGNIZED);
1563+ }
1564+ DataPointer data (der_data, der_len);
1565+
1566+ // OpenSSL might modify the pointer, so we need to make a copy before parsing.
1567+ const unsigned char * p = der_data;
1568+ EVPKeyPointer pkey (parse (&p, der_len));
1569+ if (!pkey) return EVPKeyPointer::ParseKeyResult (EVPKeyPointer::PKParseError::FAILED);
1570+ return EVPKeyPointer::ParseKeyResult (std::move (pkey));
1571+ }
1572+
1573+ EVPKeyPointer::ParseKeyResult TryParsePublicKeyPEM (
1574+ const Buffer<const unsigned char >& buffer) {
1575+ auto bp = BIOPointer::New (buffer.data , buffer.len );
1576+ if (!bp)
1577+ return EVPKeyPointer::ParseKeyResult (EVPKeyPointer::PKParseError::FAILED);
1578+
1579+ // Try parsing as SubjectPublicKeyInfo (SPKI) first.
1580+ if (auto ret = TryParsePublicKeyInner (bp, " PUBLIC KEY" ,
1581+ [](const unsigned char ** p, long l) { // NOLINT(runtime/int)
1582+ return d2i_PUBKEY (nullptr , p, l);
1583+ })) {
1584+ return ret;
1585+ }
1586+
1587+ // Maybe it is PKCS#1.
1588+ if (auto ret = TryParsePublicKeyInner (bp, " RSA PUBLIC KEY" ,
1589+ [](const unsigned char ** p, long l) { // NOLINT(runtime/int)
1590+ return d2i_PublicKey (EVP_PKEY_RSA, nullptr , p, l);
1591+ })) {
1592+ return ret;
1593+ }
1594+
1595+ // X.509 fallback.
1596+ if (auto ret = TryParsePublicKeyInner (bp, " CERTIFICATE" ,
1597+ [](const unsigned char ** p, long l) { // NOLINT(runtime/int)
1598+ X509Pointer x509 (d2i_X509 (nullptr , p, l));
1599+ return x509 ? X509_get_pubkey (x509.get ()) : nullptr ;
1600+ })) {
1601+ return ret;
1602+ };
1603+
1604+ return EVPKeyPointer::ParseKeyResult (EVPKeyPointer::PKParseError::NOT_RECOGNIZED);
1605+ }
1606+ } // namespace
1607+
1608+ EVPKeyPointer::ParseKeyResult EVPKeyPointer::TryParsePublicKey (
1609+ PKFormatType format,
1610+ PKEncodingType encoding,
1611+ const Buffer<const unsigned char >& buffer) {
1612+ if (format == PKFormatType::PEM) {
1613+ return TryParsePublicKeyPEM (buffer);
1614+ }
1615+
1616+ if (format != PKFormatType::DER) {
1617+ return ParseKeyResult (PKParseError::FAILED);
1618+ }
1619+
1620+ const unsigned char * start = buffer.data ;
1621+
1622+ EVP_PKEY* key = nullptr ;
1623+
1624+ if (encoding == PKEncodingType::PKCS1 &&
1625+ (key = d2i_PublicKey (EVP_PKEY_RSA, nullptr , &start, buffer.len ))) {
1626+ return EVPKeyPointer::ParseKeyResult (EVPKeyPointer (key));
1627+ }
1628+
1629+ if (encoding == PKEncodingType::SPKI &&
1630+ (key = d2i_PUBKEY (nullptr , &start, buffer.len ))) {
1631+ return EVPKeyPointer::ParseKeyResult (EVPKeyPointer (key));
1632+ }
1633+
1634+ return ParseKeyResult (PKParseError::FAILED);
1635+ }
1636+
14281637} // namespace ncrypto
0 commit comments