@@ -1514,6 +1514,122 @@ ossl_pkey_derive(int argc, VALUE *argv, VALUE self)
15141514 return str ;
15151515}
15161516
1517+ #ifdef HAVE_EVP_PKEY_ENCAPSULATE_INIT
1518+ /*
1519+ * call-seq:
1520+ * pkey.encapsulate -> [ciphertext, shared_secret]
1521+ *
1522+ * Performs a key encapsulation operation using the public components of
1523+ * _pkey_.
1524+ *
1525+ * See also the man page EVP_PKEY_encapsulate(3).
1526+ */
1527+ static VALUE
1528+ ossl_pkey_encapsulate (VALUE self )
1529+ {
1530+ EVP_PKEY * pkey ;
1531+ EVP_PKEY_CTX * ctx ;
1532+ VALUE ciphertext , shared_secret ;
1533+ size_t ciphertextlen , shared_secretlen ;
1534+ int state ;
1535+
1536+ GetPKey (self , pkey );
1537+ ctx = EVP_PKEY_CTX_new (pkey , /* engine */ NULL );
1538+ if (!ctx )
1539+ ossl_raise (ePKeyError , "EVP_PKEY_CTX_new" );
1540+ if (EVP_PKEY_encapsulate_init (ctx , NULL ) <= 0 ) {
1541+ EVP_PKEY_CTX_free (ctx );
1542+ ossl_raise (ePKeyError , "EVP_PKEY_encapsulate_init" );
1543+ }
1544+ if (EVP_PKEY_encapsulate (ctx , NULL , & ciphertextlen , NULL , & shared_secretlen ) <= 0 ) {
1545+ EVP_PKEY_CTX_free (ctx );
1546+ ossl_raise (ePKeyError , "EVP_PKEY_encapsulate" );
1547+ }
1548+ if (ciphertextlen > LONG_MAX || shared_secretlen > LONG_MAX ) {
1549+ EVP_PKEY_CTX_free (ctx );
1550+ rb_raise (ePKeyError , "encapsulated data would be too large" );
1551+ }
1552+ ciphertext = ossl_str_new (NULL , (long )ciphertextlen , & state );
1553+ if (state ) {
1554+ EVP_PKEY_CTX_free (ctx );
1555+ rb_jump_tag (state );
1556+ }
1557+ shared_secret = ossl_str_new (NULL , (long )shared_secretlen , & state );
1558+ if (state ) {
1559+ EVP_PKEY_CTX_free (ctx );
1560+ rb_jump_tag (state );
1561+ }
1562+ if (EVP_PKEY_encapsulate (ctx ,
1563+ (unsigned char * )RSTRING_PTR (ciphertext ),
1564+ & ciphertextlen ,
1565+ (unsigned char * )RSTRING_PTR (shared_secret ),
1566+ & shared_secretlen ) <= 0 ) {
1567+ EVP_PKEY_CTX_free (ctx );
1568+ ossl_raise (ePKeyError , "EVP_PKEY_encapsulate" );
1569+ }
1570+ EVP_PKEY_CTX_free (ctx );
1571+ rb_str_set_len (ciphertext , ciphertextlen );
1572+ rb_str_set_len (shared_secret , shared_secretlen );
1573+ return rb_assoc_new (ciphertext , shared_secret );
1574+ }
1575+
1576+ /*
1577+ * call-seq:
1578+ * pkey.decapsulate(ciphertext) -> shared_secret
1579+ *
1580+ * Performs a key decapsulation operation using the private components of
1581+ * _pkey_.
1582+ *
1583+ * See also the man page EVP_PKEY_decapsulate(3).
1584+ */
1585+ static VALUE
1586+ ossl_pkey_decapsulate (VALUE self , VALUE ciphertext )
1587+ {
1588+ EVP_PKEY * pkey ;
1589+ EVP_PKEY_CTX * ctx ;
1590+ VALUE shared_secret ;
1591+ size_t shared_secretlen ;
1592+ int state ;
1593+
1594+ GetPKey (self , pkey );
1595+ StringValue (ciphertext );
1596+
1597+ ctx = EVP_PKEY_CTX_new (pkey , /* engine */ NULL );
1598+ if (!ctx )
1599+ ossl_raise (ePKeyError , "EVP_PKEY_CTX_new" );
1600+ if (EVP_PKEY_decapsulate_init (ctx , NULL ) <= 0 ) {
1601+ EVP_PKEY_CTX_free (ctx );
1602+ ossl_raise (ePKeyError , "EVP_PKEY_decapsulate_init" );
1603+ }
1604+ if (EVP_PKEY_decapsulate (ctx , NULL , & shared_secretlen ,
1605+ (unsigned char * )RSTRING_PTR (ciphertext ),
1606+ RSTRING_LEN (ciphertext )) <= 0 ) {
1607+ EVP_PKEY_CTX_free (ctx );
1608+ ossl_raise (ePKeyError , "EVP_PKEY_decapsulate" );
1609+ }
1610+ if (shared_secretlen > LONG_MAX ) {
1611+ EVP_PKEY_CTX_free (ctx );
1612+ rb_raise (ePKeyError , "decapsulated data would be too large" );
1613+ }
1614+ shared_secret = ossl_str_new (NULL , (long )shared_secretlen , & state );
1615+ if (state ) {
1616+ EVP_PKEY_CTX_free (ctx );
1617+ rb_jump_tag (state );
1618+ }
1619+ if (EVP_PKEY_decapsulate (ctx ,
1620+ (unsigned char * )RSTRING_PTR (shared_secret ),
1621+ & shared_secretlen ,
1622+ (unsigned char * )RSTRING_PTR (ciphertext ),
1623+ RSTRING_LEN (ciphertext )) <= 0 ) {
1624+ EVP_PKEY_CTX_free (ctx );
1625+ ossl_raise (ePKeyError , "EVP_PKEY_decapsulate" );
1626+ }
1627+ EVP_PKEY_CTX_free (ctx );
1628+ rb_str_set_len (shared_secret , shared_secretlen );
1629+ return shared_secret ;
1630+ }
1631+ #endif
1632+
15171633/*
15181634 * call-seq:
15191635 * pkey.encrypt(data [, options]) -> string
@@ -1769,6 +1885,10 @@ Init_ossl_pkey(void)
17691885 rb_define_method (cPKey , "verify_raw" , ossl_pkey_verify_raw , -1 );
17701886 rb_define_method (cPKey , "verify_recover" , ossl_pkey_verify_recover , -1 );
17711887 rb_define_method (cPKey , "derive" , ossl_pkey_derive , -1 );
1888+ #ifdef HAVE_EVP_PKEY_ENCAPSULATE_INIT
1889+ rb_define_method (cPKey , "encapsulate" , ossl_pkey_encapsulate , 0 );
1890+ rb_define_method (cPKey , "decapsulate" , ossl_pkey_decapsulate , 1 );
1891+ #endif
17721892 rb_define_method (cPKey , "encrypt" , ossl_pkey_encrypt , -1 );
17731893 rb_define_method (cPKey , "decrypt" , ossl_pkey_decrypt , -1 );
17741894
0 commit comments