@@ -391,11 +391,35 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_openssl_random_pseudo_bytes, 0, 0, 1)
391
391
ZEND_ARG_INFO (0 , length )
392
392
ZEND_ARG_INFO (1 , result_is_strong )
393
393
ZEND_END_ARG_INFO ()
394
+
395
+ ZEND_BEGIN_ARG_INFO_EX (arginfo_openssl_spki_new , 0 , 0 , 2 )
396
+ ZEND_ARG_INFO (0 , privkey )
397
+ ZEND_ARG_INFO (0 , challenge )
398
+ ZEND_ARG_INFO (0 , algo )
399
+ ZEND_END_ARG_INFO ()
400
+
401
+ ZEND_BEGIN_ARG_INFO (arginfo_openssl_spki_verify , 0 )
402
+ ZEND_ARG_INFO (0 , spki )
403
+ ZEND_END_ARG_INFO ()
404
+
405
+ ZEND_BEGIN_ARG_INFO (arginfo_openssl_spki_export , 0 )
406
+ ZEND_ARG_INFO (0 , spki )
407
+ ZEND_END_ARG_INFO ()
408
+
409
+ ZEND_BEGIN_ARG_INFO (arginfo_openssl_spki_export_challenge , 0 )
410
+ ZEND_ARG_INFO (0 , spki )
411
+ ZEND_END_ARG_INFO ()
394
412
/* }}} */
395
413
396
414
/* {{{ openssl_functions[]
397
415
*/
398
416
const zend_function_entry openssl_functions [] = {
417
+ /* spki functions */
418
+ PHP_FE (openssl_spki_new , arginfo_openssl_spki_new )
419
+ PHP_FE (openssl_spki_verify , arginfo_openssl_spki_verify )
420
+ PHP_FE (openssl_spki_export , arginfo_openssl_spki_export )
421
+ PHP_FE (openssl_spki_export_challenge , arginfo_openssl_spki_export_challenge )
422
+
399
423
/* public/private key functions */
400
424
PHP_FE (openssl_pkey_free , arginfo_openssl_pkey_free )
401
425
PHP_FE (openssl_pkey_new , arginfo_openssl_pkey_new )
@@ -790,6 +814,7 @@ static int add_oid_section(struct php_x509_request * req TSRMLS_DC) /* {{{ */
790
814
791
815
static const EVP_CIPHER * php_openssl_get_evp_cipher_from_algo (long algo );
792
816
817
+ int openssl_spki_cleanup (const char * src , char * dest );
793
818
794
819
static int php_openssl_parse_config (struct php_x509_request * req , zval * optional_args TSRMLS_DC ) /* {{{ */
795
820
{
@@ -1334,6 +1359,280 @@ PHP_FUNCTION(openssl_x509_export_to_file)
1334
1359
}
1335
1360
/* }}} */
1336
1361
1362
+ /* {{{ proto string openssl_spki_new(mixed zpkey, string challenge [, mixed method])
1363
+ Creates new private key (or uses existing) and creates a new spki cert
1364
+ outputting results to var */
1365
+ PHP_FUNCTION (openssl_spki_new )
1366
+ {
1367
+ int challenge_len ;
1368
+ char * challenge = NULL , * spkstr = NULL , * s = NULL ;
1369
+ long keyresource = -1 ;
1370
+ const char * spkac = "SPKAC=" ;
1371
+ long algo = OPENSSL_ALGO_MD5 ;
1372
+
1373
+ zval * method = NULL ;
1374
+ zval * zpkey = NULL ;
1375
+ EVP_PKEY * pkey = NULL ;
1376
+ NETSCAPE_SPKI * spki = NULL ;
1377
+ const EVP_MD * mdtype ;
1378
+
1379
+ if (zend_parse_parameters (ZEND_NUM_ARGS () TSRMLS_CC , "rs|z" , & zpkey , & challenge , & challenge_len , & method ) == FAILURE ) {
1380
+ return ;
1381
+ }
1382
+ RETVAL_FALSE ;
1383
+
1384
+ pkey = php_openssl_evp_from_zval (& zpkey , 0 , challenge , 1 , & keyresource TSRMLS_CC );
1385
+
1386
+ if (pkey == NULL ) {
1387
+ php_error_docref (NULL TSRMLS_CC , E_WARNING , "Unable to use supplied private key" );
1388
+ goto cleanup ;
1389
+ }
1390
+
1391
+ if (method != NULL ) {
1392
+ if (Z_TYPE_P (method ) == IS_LONG ) {
1393
+ algo = Z_LVAL_P (method );
1394
+ } else {
1395
+ php_error_docref (NULL TSRMLS_CC , E_WARNING , "Algorithm must be of supported type" );
1396
+ goto cleanup ;
1397
+ }
1398
+ }
1399
+ mdtype = php_openssl_get_evp_md_from_algo (algo );
1400
+
1401
+ if (!mdtype ) {
1402
+ php_error_docref (NULL TSRMLS_CC , E_WARNING , "Unknown signature algorithm ");
1403
+ goto cleanup ;
1404
+ }
1405
+
1406
+ if ((spki = NETSCAPE_SPKI_new ()) == NULL ) {
1407
+ php_error_docref (NULL TSRMLS_CC , E_WARNING , "Unable to create new SPKAC" );
1408
+ goto cleanup ;
1409
+ }
1410
+
1411
+ if (challenge ) {
1412
+ ASN1_STRING_set (spki -> spkac -> challenge , challenge , (int )strlen (challenge ));
1413
+ }
1414
+
1415
+ if (!NETSCAPE_SPKI_set_pubkey (spki , pkey )) {
1416
+ php_error_docref (NULL TSRMLS_CC , E_WARNING , "Unable to embed public key" );
1417
+ goto cleanup ;
1418
+ }
1419
+
1420
+ if (!NETSCAPE_SPKI_sign (spki , pkey , mdtype )) {
1421
+ php_error_docref (NULL TSRMLS_CC , E_WARNING , "Unable to sign with specified algorithm" );
1422
+ goto cleanup ;
1423
+ }
1424
+
1425
+ spkstr = NETSCAPE_SPKI_b64_encode (spki );
1426
+ if (!spkstr ){
1427
+ php_error_docref (NULL TSRMLS_CC , E_WARNING , "Unable to encode SPKAC" );
1428
+ goto cleanup ;
1429
+ }
1430
+
1431
+ s = emalloc (strlen (spkac ) + strlen (spkstr ) + 1 );
1432
+ sprintf (s , "%s%s" , spkac , spkstr );
1433
+
1434
+ RETVAL_STRINGL (s , strlen (s ), 0 );
1435
+ goto cleanup ;
1436
+
1437
+ cleanup :
1438
+
1439
+ if (keyresource == -1 && spki != NULL ) {
1440
+ NETSCAPE_SPKI_free (spki );
1441
+ }
1442
+ if (keyresource == -1 && pkey != NULL ) {
1443
+ EVP_PKEY_free (pkey );
1444
+ }
1445
+ if (keyresource == -1 && spkstr != NULL ) {
1446
+ efree (spkstr );
1447
+ }
1448
+
1449
+ if (strlen (s ) <= 0 ) {
1450
+ RETVAL_FALSE ;
1451
+ }
1452
+
1453
+ if (keyresource == -1 && s != NULL ) {
1454
+ efree (s );
1455
+ }
1456
+ }
1457
+ /* }}} */
1458
+
1459
+ /* {{{ proto bool openssl_spki_verify(string spki)
1460
+ Verifies spki returns boolean */
1461
+ PHP_FUNCTION (openssl_spki_verify )
1462
+ {
1463
+ int spkstr_len , i = 0 ;
1464
+ char * spkstr = NULL , * spkstr_cleaned = NULL ;
1465
+
1466
+ EVP_PKEY * pkey = NULL ;
1467
+ NETSCAPE_SPKI * spki = NULL ;
1468
+
1469
+ if (zend_parse_parameters (ZEND_NUM_ARGS () TSRMLS_CC , "s" , & spkstr , & spkstr_len ) == FAILURE ) {
1470
+ return ;
1471
+ }
1472
+ RETVAL_FALSE ;
1473
+
1474
+ if (spkstr == NULL ) {
1475
+ php_error_docref (NULL TSRMLS_CC , E_WARNING , "Unable to use supplied SPKAC" );
1476
+ goto cleanup ;
1477
+ }
1478
+
1479
+ spkstr_cleaned = emalloc (spkstr_len + 1 );
1480
+ openssl_spki_cleanup (spkstr , spkstr_cleaned );
1481
+
1482
+ if (strlen (spkstr_cleaned )<=0 ) {
1483
+ php_error_docref (NULL TSRMLS_CC , E_WARNING , "Invalid SPKAC ");
1484
+ goto cleanup ;
1485
+ }
1486
+
1487
+ spki = NETSCAPE_SPKI_b64_decode (spkstr_cleaned , strlen (spkstr_cleaned ));
1488
+ if (spki == NULL ) {
1489
+ php_error_docref (NULL TSRMLS_CC , E_WARNING , "Unable to decode supplied SPKAC" );
1490
+ goto cleanup ;
1491
+ }
1492
+
1493
+ pkey = X509_PUBKEY_get (spki -> spkac -> pubkey );
1494
+ if (pkey == NULL ) {
1495
+ php_error_docref (NULL TSRMLS_CC , E_WARNING , "Unable to aquire signed public key" );
1496
+ goto cleanup ;
1497
+ }
1498
+
1499
+ i = NETSCAPE_SPKI_verify (spki , pkey );
1500
+ goto cleanup ;
1501
+
1502
+ cleanup :
1503
+ if (spki != NULL ) {
1504
+ NETSCAPE_SPKI_free (spki );
1505
+ }
1506
+ if (pkey != NULL ) {
1507
+ EVP_PKEY_free (pkey );
1508
+ }
1509
+ if (spkstr_cleaned != NULL ) {
1510
+ efree (spkstr_cleaned );
1511
+ }
1512
+
1513
+ if (i > 0 ) {
1514
+ RETVAL_TRUE ;
1515
+ }
1516
+ }
1517
+ /* }}} */
1518
+
1519
+ /* {{{ proto string openssl_spki_export(string spki)
1520
+ Exports public key from existing spki to var */
1521
+ PHP_FUNCTION (openssl_spki_export )
1522
+ {
1523
+ int spkstr_len ;
1524
+ char * spkstr = NULL , * spkstr_cleaned = NULL , * s = NULL ;
1525
+
1526
+ EVP_PKEY * pkey = NULL ;
1527
+ NETSCAPE_SPKI * spki = NULL ;
1528
+ BIO * out = BIO_new (BIO_s_mem ());
1529
+ BUF_MEM * bio_buf ;
1530
+
1531
+ if (zend_parse_parameters (ZEND_NUM_ARGS () TSRMLS_CC , "s" , & spkstr , & spkstr_len ) == FAILURE ) {
1532
+ return ;
1533
+ }
1534
+ RETVAL_FALSE ;
1535
+
1536
+ if (spkstr == NULL ) {
1537
+ php_error_docref (NULL TSRMLS_CC , E_WARNING , "Unable to use supplied SPKAC" );
1538
+ goto cleanup ;
1539
+ }
1540
+
1541
+ spkstr_cleaned = emalloc (spkstr_len + 1 );
1542
+ openssl_spki_cleanup (spkstr , spkstr_cleaned );
1543
+
1544
+ spki = NETSCAPE_SPKI_b64_decode (spkstr_cleaned , strlen (spkstr_cleaned ));
1545
+ if (spki == NULL ) {
1546
+ php_error_docref (NULL TSRMLS_CC , E_WARNING , "Unable to decode supplied SPKAC" );
1547
+ goto cleanup ;
1548
+ }
1549
+
1550
+ pkey = X509_PUBKEY_get (spki -> spkac -> pubkey );
1551
+ if (pkey == NULL ) {
1552
+ php_error_docref (NULL TSRMLS_CC , E_WARNING , "Unable to aquire signed public key" );
1553
+ goto cleanup ;
1554
+ }
1555
+
1556
+ out = BIO_new_fp (stdout , BIO_NOCLOSE );
1557
+ PEM_write_bio_PUBKEY (out , pkey );
1558
+ goto cleanup ;
1559
+
1560
+ cleanup :
1561
+
1562
+ if (spki != NULL ) {
1563
+ NETSCAPE_SPKI_free (spki );
1564
+ }
1565
+ if (out != NULL ) {
1566
+ BIO_free_all (out );
1567
+ }
1568
+ if (pkey != NULL ) {
1569
+ EVP_PKEY_free (pkey );
1570
+ }
1571
+ if (spkstr_cleaned != NULL ) {
1572
+ efree (spkstr_cleaned );
1573
+ }
1574
+ if (s != NULL ) {
1575
+ efree (s );
1576
+ }
1577
+ }
1578
+ /* }}} */
1579
+
1580
+ /* {{{ proto string openssl_spki_export_challenge(string spki)
1581
+ Exports spkac challenge from existing spki to var */
1582
+ PHP_FUNCTION (openssl_spki_export_challenge )
1583
+ {
1584
+ int spkstr_len ;
1585
+ char * spkstr = NULL , * spkstr_cleaned = NULL ;
1586
+
1587
+ NETSCAPE_SPKI * spki = NULL ;
1588
+
1589
+ if (zend_parse_parameters (ZEND_NUM_ARGS () TSRMLS_CC , "s" , & spkstr , & spkstr_len ) == FAILURE ) {
1590
+ return ;
1591
+ }
1592
+ RETVAL_FALSE ;
1593
+
1594
+ if (spkstr == NULL ) {
1595
+ php_error_docref (NULL TSRMLS_CC , E_WARNING , "Unable to use supplied SPKAC" );
1596
+ goto cleanup ;
1597
+ }
1598
+
1599
+ spkstr_cleaned = emalloc (spkstr_len + 1 );
1600
+ openssl_spki_cleanup (spkstr , spkstr_cleaned );
1601
+
1602
+ spki = NETSCAPE_SPKI_b64_decode (spkstr_cleaned , strlen (spkstr_cleaned ));
1603
+ if (spki == NULL ) {
1604
+ php_error_docref (NULL TSRMLS_CC , E_WARNING , "Unable to decode SPKAC" );
1605
+ goto cleanup ;
1606
+ }
1607
+
1608
+ RETVAL_STRING (ASN1_STRING_data (spki -> spkac -> challenge ), 1 );
1609
+ goto cleanup ;
1610
+
1611
+ cleanup :
1612
+ if (spkstr_cleaned != NULL ) {
1613
+ efree (spkstr_cleaned );
1614
+ }
1615
+ }
1616
+ /* }}} */
1617
+
1618
+ /* {{{ strip line endings from spkac */
1619
+ int openssl_spki_cleanup (const char * src , char * dest )
1620
+ {
1621
+ int removed = 0 ;
1622
+
1623
+ while (* src ) {
1624
+ if (* src != '\n' && * src != '\r' ) {
1625
+ * dest ++ = * src ;
1626
+ } else {
1627
+ ++ removed ;
1628
+ }
1629
+ ++ src ;
1630
+ }
1631
+ * dest = 0 ;
1632
+ return removed ;
1633
+ }
1634
+ /* }}} */
1635
+
1337
1636
/* {{{ proto bool openssl_x509_export(mixed x509, string &out [, bool notext = true])
1338
1637
Exports a CERT to file or a var */
1339
1638
PHP_FUNCTION (openssl_x509_export )
0 commit comments