@@ -1425,4 +1425,213 @@ DataPointer pbkdf2(const EVP_MD* md,
1425
1425
return {};
1426
1426
}
1427
1427
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
+
1428
1637
} // namespace ncrypto
0 commit comments