@@ -1384,4 +1384,213 @@ DataPointer pbkdf2(const EVP_MD* md,
1384
1384
return {};
1385
1385
}
1386
1386
1387
+ // ============================================================================
1388
+
1389
+ EVPKeyPointer EVPKeyPointer::New () {
1390
+ return EVPKeyPointer (EVP_PKEY_new ());
1391
+ }
1392
+
1393
+ EVPKeyPointer EVPKeyPointer::NewRawPublic (int id, const Buffer<const unsigned char >& data) {
1394
+ if (id == 0 ) return {};
1395
+ return EVPKeyPointer (EVP_PKEY_new_raw_public_key (id, nullptr , data.data , data.len ));
1396
+ }
1397
+
1398
+ EVPKeyPointer EVPKeyPointer::NewRawPrivate (int id, const Buffer<const unsigned char >& data) {
1399
+ if (id == 0 ) return {};
1400
+ return EVPKeyPointer (EVP_PKEY_new_raw_private_key (id, nullptr , data.data , data.len ));
1401
+ }
1402
+
1403
+ EVPKeyPointer::EVPKeyPointer (EVP_PKEY* pkey) : pkey_(pkey) {}
1404
+
1405
+ EVPKeyPointer::EVPKeyPointer (EVPKeyPointer&& other) noexcept
1406
+ : pkey_(other.release()) {}
1407
+
1408
+ EVPKeyPointer& EVPKeyPointer::operator =(EVPKeyPointer&& other) noexcept {
1409
+ if (this == &other) return *this ;
1410
+ this ->~EVPKeyPointer ();
1411
+ return *new (this ) EVPKeyPointer (std::move (other));
1412
+ }
1413
+
1414
+ EVPKeyPointer::~EVPKeyPointer () { reset (); }
1415
+
1416
+ void EVPKeyPointer::reset (EVP_PKEY* pkey) {
1417
+ pkey_.reset (pkey);
1418
+ }
1419
+
1420
+ EVP_PKEY* EVPKeyPointer::release () {
1421
+ return pkey_.release ();
1422
+ }
1423
+
1424
+ int EVPKeyPointer::id (const EVP_PKEY* key) {
1425
+ if (key == nullptr ) return 0 ;
1426
+ return EVP_PKEY_id (key);
1427
+ }
1428
+
1429
+ int EVPKeyPointer::base_id (const EVP_PKEY* key) {
1430
+ if (key == nullptr ) return 0 ;
1431
+ return EVP_PKEY_base_id (key);
1432
+ }
1433
+
1434
+ int EVPKeyPointer::id () const {
1435
+ return id (get ());
1436
+ }
1437
+
1438
+ int EVPKeyPointer::base_id () const {
1439
+ return base_id (get ());
1440
+ }
1441
+
1442
+ int EVPKeyPointer::bits () const {
1443
+ if (get () == nullptr ) return 0 ;
1444
+ return EVP_PKEY_bits (get ());
1445
+ }
1446
+
1447
+ size_t EVPKeyPointer::size () const {
1448
+ if (get () == nullptr ) return 0 ;
1449
+ return EVP_PKEY_size (get ());
1450
+ }
1451
+
1452
+ EVPKeyCtxPointer EVPKeyPointer::newCtx () const {
1453
+ if (!pkey_) return {};
1454
+ return EVPKeyCtxPointer (EVP_PKEY_CTX_new (get (), nullptr ));
1455
+ }
1456
+
1457
+ size_t EVPKeyPointer::rawPublicKeySize () const {
1458
+ if (!pkey_) return 0 ;
1459
+ size_t len = 0 ;
1460
+ if (EVP_PKEY_get_raw_public_key (get (), nullptr , &len) == 1 ) return len;
1461
+ return 0 ;
1462
+ }
1463
+
1464
+ size_t EVPKeyPointer::rawPrivateKeySize () const {
1465
+ if (!pkey_) return 0 ;
1466
+ size_t len = 0 ;
1467
+ if (EVP_PKEY_get_raw_private_key (get (), nullptr , &len) == 1 ) return len;
1468
+ return 0 ;
1469
+ }
1470
+
1471
+ DataPointer EVPKeyPointer::rawPublicKey () const {
1472
+ if (!pkey_) return {};
1473
+ if (auto data = DataPointer::Alloc (rawPublicKeySize ())) {
1474
+ const Buffer<unsigned char > buf = data;
1475
+ size_t len = data.size ();
1476
+ if (EVP_PKEY_get_raw_public_key (get (),
1477
+ buf.data ,
1478
+ &len) != 1 ) return {};
1479
+ return data;
1480
+ }
1481
+ return {};
1482
+ }
1483
+
1484
+ DataPointer EVPKeyPointer::rawPrivateKey () const {
1485
+ if (!pkey_) return {};
1486
+ if (auto data = DataPointer::Alloc (rawPrivateKeySize ())) {
1487
+ const Buffer<unsigned char > buf = data;
1488
+ size_t len = data.size ();
1489
+ if (EVP_PKEY_get_raw_private_key (get (),
1490
+ buf.data ,
1491
+ &len) != 1 ) return {};
1492
+ return data;
1493
+ }
1494
+ return {};
1495
+ }
1496
+
1497
+ BIOPointer EVPKeyPointer::derPublicKey () const {
1498
+ if (!pkey_) return {};
1499
+ auto bio = BIOPointer::NewMem ();
1500
+ if (!bio) return {};
1501
+ if (!i2d_PUBKEY_bio (bio.get (), get ())) return {};
1502
+ return bio;
1503
+ }
1504
+
1505
+ namespace {
1506
+ EVPKeyPointer::ParseKeyResult TryParsePublicKeyInner (
1507
+ const BIOPointer& bp,
1508
+ const char * name,
1509
+ auto && parse) {
1510
+ if (!bp.resetBio ()) {
1511
+ return EVPKeyPointer::ParseKeyResult (EVPKeyPointer::PKParseError::FAILED);
1512
+ }
1513
+ unsigned char * der_data;
1514
+ long der_len;
1515
+
1516
+ // This skips surrounding data and decodes PEM to DER.
1517
+ {
1518
+ MarkPopErrorOnReturn mark_pop_error_on_return;
1519
+ if (PEM_bytes_read_bio (&der_data, &der_len, nullptr , name,
1520
+ bp.get (), nullptr , nullptr ) != 1 )
1521
+ return EVPKeyPointer::ParseKeyResult (EVPKeyPointer::PKParseError::NOT_RECOGNIZED);
1522
+ }
1523
+ DataPointer data (der_data, der_len);
1524
+
1525
+ // OpenSSL might modify the pointer, so we need to make a copy before parsing.
1526
+ const unsigned char * p = der_data;
1527
+ EVPKeyPointer pkey (parse (&p, der_len));
1528
+ if (!pkey) return EVPKeyPointer::ParseKeyResult (EVPKeyPointer::PKParseError::FAILED);
1529
+ return EVPKeyPointer::ParseKeyResult (std::move (pkey));
1530
+ }
1531
+
1532
+ EVPKeyPointer::ParseKeyResult TryParsePublicKeyPEM (
1533
+ const Buffer<const unsigned char >& buffer) {
1534
+ auto bp = BIOPointer::New (buffer.data , buffer.len );
1535
+ if (!bp)
1536
+ return EVPKeyPointer::ParseKeyResult (EVPKeyPointer::PKParseError::FAILED);
1537
+
1538
+ // Try parsing as SubjectPublicKeyInfo (SPKI) first.
1539
+ if (auto ret = TryParsePublicKeyInner (bp, " PUBLIC KEY" ,
1540
+ [](const unsigned char ** p, long l) { // NOLINT(runtime/int)
1541
+ return d2i_PUBKEY (nullptr , p, l);
1542
+ })) {
1543
+ return ret;
1544
+ }
1545
+
1546
+ // Maybe it is PKCS#1.
1547
+ if (auto ret = TryParsePublicKeyInner (bp, " RSA PUBLIC KEY" ,
1548
+ [](const unsigned char ** p, long l) { // NOLINT(runtime/int)
1549
+ return d2i_PublicKey (EVP_PKEY_RSA, nullptr , p, l);
1550
+ })) {
1551
+ return ret;
1552
+ }
1553
+
1554
+ // X.509 fallback.
1555
+ if (auto ret = TryParsePublicKeyInner (bp, " CERTIFICATE" ,
1556
+ [](const unsigned char ** p, long l) { // NOLINT(runtime/int)
1557
+ X509Pointer x509 (d2i_X509 (nullptr , p, l));
1558
+ return x509 ? X509_get_pubkey (x509.get ()) : nullptr ;
1559
+ })) {
1560
+ return ret;
1561
+ };
1562
+
1563
+ return EVPKeyPointer::ParseKeyResult (EVPKeyPointer::PKParseError::NOT_RECOGNIZED);
1564
+ }
1565
+ } // namespace
1566
+
1567
+ EVPKeyPointer::ParseKeyResult EVPKeyPointer::TryParsePublicKey (
1568
+ PKFormatType format,
1569
+ PKEncodingType encoding,
1570
+ const Buffer<const unsigned char >& buffer) {
1571
+ if (format == PKFormatType::PEM) {
1572
+ return TryParsePublicKeyPEM (buffer);
1573
+ }
1574
+
1575
+ if (format != PKFormatType::DER) {
1576
+ return ParseKeyResult (PKParseError::FAILED);
1577
+ }
1578
+
1579
+ const unsigned char * start = buffer.data ;
1580
+
1581
+ EVP_PKEY* key = nullptr ;
1582
+
1583
+ if (encoding == PKEncodingType::PKCS1 &&
1584
+ (key = d2i_PublicKey (EVP_PKEY_RSA, nullptr , &start, buffer.len ))) {
1585
+ return EVPKeyPointer::ParseKeyResult (EVPKeyPointer (key));
1586
+ }
1587
+
1588
+ if (encoding == PKEncodingType::SPKI &&
1589
+ (key = d2i_PUBKEY (nullptr , &start, buffer.len ))) {
1590
+ return EVPKeyPointer::ParseKeyResult (EVPKeyPointer (key));
1591
+ }
1592
+
1593
+ return ParseKeyResult (PKParseError::FAILED);
1594
+ }
1595
+
1387
1596
} // namespace ncrypto
0 commit comments