diff options
Diffstat (limited to 'test/openssl')
33 files changed, 1669 insertions, 989 deletions
diff --git a/test/openssl/fixtures/pkey/dsa1024.pem b/test/openssl/fixtures/pkey/dsa1024.pem deleted file mode 100644 index 1bf498895e..0000000000 --- a/test/openssl/fixtures/pkey/dsa1024.pem +++ /dev/null @@ -1,12 +0,0 @@ ------BEGIN DSA PRIVATE KEY----- -MIIBugIBAAKBgQCH9aAoXvWWThIjkA6D+nI1F9ksF9iDq594rkiGNOT9sPDOdB+n -D+qeeeeloRlj19ymCSADPI0ZLRgkchkAEnY2RnqnhHOjVf/roGgRbW+iQDMbQ9wa -/pvc6/fAbsu1goE1hBYjm98/sZEeXavj8tR56IXnjF1b6Nx0+sgeUKFKEQIVAMiz -4BJUFeTtddyM4uadBM7HKLPRAoGAZdLBSYNGiij7vAjesF5mGUKTIgPd+JKuBEDx -OaBclsgfdoyoF/TMOkIty+PVlYD+//Vl2xnoUEIRaMXHwHfm0r2xUX++oeRaSScg -YizJdUxe5jvBuBszGPRc/mGpb9YvP0sB+FL1KmuxYmdODfCe51zl8uM/CVhouJ3w -DjmRGscCgYAuFlfC7p+e8huCKydfcv/beftqjewiOPpQ3u5uI6KPCtCJPpDhs3+4 -IihH2cPsAlqwGF4tlibW1+/z/OZ1AZinPK3y7b2jSJASEaPeEltVzB92hcd1khk2 -jTYcmSsV4VddplOPK9czytR/GbbibxsrhhgZUbd8LPbvIgaiadJ1PgIUBnJ/5vN2 -CVArsEzlPUCbohPvZnE= ------END DSA PRIVATE KEY----- diff --git a/test/openssl/fixtures/pkey/dsa256.pem b/test/openssl/fixtures/pkey/dsa256.pem deleted file mode 100644 index d9a407f736..0000000000 --- a/test/openssl/fixtures/pkey/dsa256.pem +++ /dev/null @@ -1,8 +0,0 @@ ------BEGIN DSA PRIVATE KEY----- -MIH3AgEAAkEAhk2libbY2a8y2Pt21+YPYGZeW6wzaW2yfj5oiClXro9XMR7XWLkE -9B7XxLNFCS2gmCCdMsMW1HulaHtLFQmB2wIVAM43JZrcgpu6ajZ01VkLc93gu/Ed -AkAOhujZrrKV5CzBKutKLb0GVyVWmdC7InoNSMZEeGU72rT96IjM59YzoqmD0pGM -3I1o4cGqg1D1DfM1rQlnN1eSAkBq6xXfEDwJ1mLNxF6q8Zm/ugFYWR5xcX/3wFiT -b4+EjHP/DbNh9Vm5wcfnDBJ1zKvrMEf2xqngYdrV/3CiGJeKAhRvL57QvJZcQGvn -ISNX5cMzFHRW3Q== ------END DSA PRIVATE KEY----- diff --git a/test/openssl/fixtures/pkey/dsa512.pem b/test/openssl/fixtures/pkey/dsa512.pem deleted file mode 100644 index 962c41cc67..0000000000 --- a/test/openssl/fixtures/pkey/dsa512.pem +++ /dev/null @@ -1,8 +0,0 @@ ------BEGIN DSA PRIVATE KEY----- -MIH4AgEAAkEA5lB4GvEwjrsMlGDqGsxrbqeFRh6o9OWt6FgTYiEEHaOYhkIxv0Ok -RZPDNwOG997mDjBnvDJ1i56OmS3MbTnovwIVAJgub/aDrSDB4DZGH7UyarcaGy6D -AkB9HdFw/3td8K4l1FZHv7TCZeJ3ZLb7dF3TWoGUP003RCqoji3/lHdKoVdTQNuR -S/m6DlCwhjRjiQ/lBRgCLCcaAkEAjN891JBjzpMj4bWgsACmMggFf57DS0Ti+5++ -Q1VB8qkJN7rA7/2HrCR3gTsWNb1YhAsnFsoeRscC+LxXoXi9OAIUBG98h4tilg6S -55jreJD3Se3slps= ------END DSA PRIVATE KEY----- diff --git a/test/openssl/fixtures/pkey/mldsa65-1.pem b/test/openssl/fixtures/pkey/mldsa65-1.pem new file mode 100644 index 0000000000..21f08e3ac6 --- /dev/null +++ b/test/openssl/fixtures/pkey/mldsa65-1.pem @@ -0,0 +1,88 @@ +-----BEGIN PRIVATE KEY----- +MIIP/gIBADALBglghkgBZQMEAxIEgg/qMIIP5gQg6Xunp08Ia0w6d93rvBnXnlYf +ih3Z+9IDZSRIyAGfjbQEgg/A9DPSakjm2xFsVzCHpfwcUwP5dYpJGRYwG7/eSp8b +/lJOHPmIHjOAC8jN3xS66UXcouWozGXbmieGjLzNs1HjBaJ0CEw51wQOuPLDg8nj +Pdesnqu5Ct1sNzqz0K57ixyEPrdPI+Vd7XDNaXfOytZ1d4+yFBC6cGpznQ9CiRYm +PpFEgUZSg3QzFmB0hREkB4FHhTIUZlckclcxNRRTg4UFUIVTdTcThxVyJSFFInZl +GEUnKAIEcXBUdmgwMQMhRngCFEIFBIB2BVRjEiEwI3FwAQJEEScySFh0UVdQExeB +ZDYgIUhlFUYxh1g2V2YRdohodCVgBXYIJRJCQHFGRiI0GGQENkgBFwUGNUeAMlh0 +ZgMhIWRmhyhGVEeAUUOHVVKEZHU4BQdwMjEBIIcQeBYFZhKBdwFjBlQECCJEdoYT +E3FXYlcECCNIZAF4cTaAQwYxBkd2YRE3FTIYRCYgF2SBUiBCJ1ImFjZSFDCIaAY1 +J1ExVDRRVzFGgiUIV1UBCDcVFmcIM4OGeDIXEyZXaCFzBBeBFQQxcFeIJWBmJCdw +hWMUdYFiNFAmMIEyKIRYIIeIgHA3AmNTElA3gwVmBUUHERE2AAJHUhQTJQAFAXhY +QmYDdSZHWFhHQXUkRFBWViQ4VERRF1eEN0I2VzR1dUIxg1Uid2NmcDIWdBAzITEA +AmJgh3JlgwIREgVoIiEoMCADEGSHFIGHUnJVU2I0CGRxaAR3JUVgAnJQOAQiZ2Vh +OFM3MIEHUmFzQhcEdzSBhBcYVCgEKCIiWHUBhCVxhkBjRzUzJAhDQ2F3eGdUNTEj +QQcjY3E3BnR2Q4cWIjJohyd2hCUzOIgSUodmIxY1AmaDFVBQEghncQQYQ2QIcjiB +ZWNQZGZFhHiBIQcXURQQAVg2RBQQd0aDgGQXE3Q4eHY1iERUVoUTcQIjcmh0UVci +Rhd4MRI0ZUVHNXEAIDQ2cVIGZYMiB1ZQQSYVMlZBQiAwQHJYCEUBExAjF4QwQBMT +cjdGVCckJTBFJAcXREMzAlYmhRJXgEVSESFYAAJwFXRyKBZCQwcDIFQkJWUFB4gV +F2GBiEcVEUAmcWEFREA4dEFDQwhFUQUIcHQRMRGHFTA2g0YmZxIiMjMjAQFgcHYF +IgJlFyA4RhdRgWY1FVEhM4VoUhiIQkcIeCCFZIESZjVWFjNWQEZTNGUoBiR0cgFn +hDNIAhIRdXQgaGBxNUdyBUIWAniAZIOHYTIyUYd0YXExBjEShGA1GBQ3FBZVEmEw +EhhEJQNwRjUyQnSIAVNlQjKDdIEBQQhgdSdxc2RjEmRiFyY2RRYicjQCh3AhNSZo +QzRlGDaGMzCIhRcjIocxN4cwM2gRA2WIN0NyaHR1NRVRAXIkFTR0J2NCCCEHKHYn +FSYGF3QXBwhDYUZEJmdHEWAlBCIyVRFBR2NSNgJwZgBoAgMjcYQRNAFjI2ZVVgEE +V3Y1eIREhFc1ABVEGGcUNGRnWAJYOAdlZmgWQlZncWJVNFNkBwOGRiAmJGQGNlIx +NwNwZ3WBaGIBdiNlMEVXFwFkZRRCE3ZwFxgQWFKHVxOBdxJHJBhSF0d4IlAgIRUY +UXdCWIQIKDGAhAIoVBAhdXU3AHKCiCBkF4KEhhRyU2JTIIdwdGYSCDcXIWM4QYIY +NoCFNSESeBMnciUkMxV1RYNzYUSGggMIgWVCM3aAMRcCITMgKERIEjgiUkIlNoUT +JkMjMzc3dxV1WGOCZRJSMzIhGIAgBEgicDM2CFclACBlBoYyhyNgJoOIExIoY3Qh +EFRQhFYBZoJERhNoQCIUaAIARgiCQSUXYkUgR4RnYAczh0ECOCeGdBJXExNohzZH +GFMAE2MAUUZ3NzF2FldoGCKEIzJzGDFHd3KAU4ZHUichAYUmEYVAdShYFlh3FIIl +UzQYdScUdlAAglVjBiNCJYGBKHVTNEJBMBAQEFQhJSI0diJ0dFA3KBIAg2RxcXIA +cWMBcoIEQBgAUBUyEDUwcQYTVwSCMjBCVEQiQWMThDhVE2YWZBNQhVZzY4cBhIZh +IIBBQihmh4VgJjZkJ2J1VlAB5kLlGDaGXIOc++2QqMCGeB9FnTYpHFoSXQrOjQhS +tfTln0rEelihhKhi3Bu8mdhyTSFZTShsQidqlN1/U50KnMTqII7r9QltUZqPH9sW +CswVssxnVe1GAXY/LqJPN5DEN2ZEMoAgmxLbGYB5YdKID1lj5zquaCqpDUGDI/Wi +zJ5xpFzn7nGJwedU2MBqcqlIVJg8VeIInkLL/v3y2uqD4+pewW8OewqosJOfBgjI +RH1FXcdGbnqKJk1YZ8iwVMTNoU9U8gGDI5kk/dWWqqAdxaVrsmevmNRp6wtibFG6 +FxrSRb7hOP8IVv7TkMA+Cv4MRs0UhYJ2W8x0G0LxP4M+m3cAJkaHyHDda1NHjfTV +zG9hWK8Ad7t+F9hw5++KBPlkW+/sX4eYpOlC/XjpMp1W6WIr9oIbRp6RXKNUuBXQ +58uNAmq6peDenbwsmiBKG+RWntbMxtjOM9bo/JXMV9dIT/KIbljl2C/4TRbWy0D3 +KfZlvAHpiw2oH/vaLUFbIg7sK823keZA/uSFJ2KSPBVC6+AYX5tM/P/KKLJmFoVY +U7h4F/SDCbOt5PJu9yg+fN6ftBT3a2723TAx7M8+WqPrvvOB5UFJRNCcpwnjqriz +8ENLgoze5wm2sIk+QvB15tFG0n3+9eTOjD+q0dJDSxq5xAuAalBoFp7vSt2x1UO/ +4Nf/jXvJT2nXjR7QgtabQRzKqbP5lHVtL0BCJeGFlbGeuAGIfNuVY0809E66sWDo +S18hNAfp9jKe0aU7MxGU6RvCB8vLK+cld/RzujyK8C307PJdzwCLEYIBMC3SvBcQ +9CpJFuPIcEVoM1RiThw/l1MAaKJ3y73ekU5p+Dd2CN4P4pCDSiVj/PAOW1c7iA2A +QBVuCfPMYJyW93toHaqpaZuD9VN3OKbtJvuMWCOIN59ERFvttv5CNQ01rhgCv3dZ +kkkFrJsmFcwsgMW1JIGozMKywFzi9yDWUL6j/ZCc8xqkfP9fYPBBTcSsUvWV9Zq6 +AU22B9j6/EUP8crw0VViacbEJy2sJgIumEQiVlVNavorpPwjtWpVQFvsBrDm6X80 +jk9H/yTKrrR6LaTH7999s/88jOLszmbX7Yt8VmMkkliml2rd6UqG9D6zq2xEj1IV +6ZT2zhVe+wHNmpkr1kYTIVsLXrHNpCWEQeHscSCzz/lg+aOv8kSfFqGq2VFjxnts +7Z88TjxzIOQk14Lzkgl0PCyHXau8i2bteCOimqRYEd3ihNcC8U9MXLYrOiv24oXM +RpkzoHGOtZoAie6k1Xj6aDwIl2mTBHg5BF0A4U+d/z7wS8Gr9nEc574s9OyKAZn6 +5L/1GgpWa0e2buxn8fkPAMptY0773prqKqwvV/SWdvUJ4B4HLNLsU70+N4XAZlRS +7saNkghBkrD/WobJQwa/9OWWa5Gw6Frurr0AmnBU+EN7u6niFwARsa9f1yjuW8IJ +tLD7H+Yu2bGouHWpeoXQHwqFxl+me7rQ/ePvOYQk/SzlzvroaqAGECrDoHU3kzhn +rhJLueA9b0j3u0/+CQaNOFPWb6GAjmafVWpBcXtOSkHVUXitclURlITEwe47tn+g +XffSw3k1q3XBKkFkJQrgPa2IbpAWvFKA7rOInY/b8N/lCI0bZAei2OOR2/MLifkx +F3L8daWXslp7QSlIjUXwtgdD6CwQsEui99dZvTYlSxzUKC9nsF0oPYxWpHAcuoCE +pQCR1CuyuGkDCaod2VNWqWOcZ5QXjEtbVHFO8qJdePJPKWV+0YcltaR4X5q2Pts9 +4a0SJMSM/tXrUi9g9RjjnB+F++rc4a5FrQ2r7FDXudk7NUEoJPyBvBDeowiSmXvv +SHrL6WsQgf8n5sZxfA0uqs+8OMSLLNj72CSoBQMJNVJgYQkSyBuHl6Zk59+k/WeJ +wX1qevXwaC6JrdF+naRcp16tNv+7230GPO1d3+X3zZOtAEuAzk6kw3da8Y15qZ5j +FqzXPO8TsURyOf4Fp+kxpETSQ+mf8Do0hWzUYE8Cj2EFcwuE2Q7+c1ZHAFpQNk1j +T4vR//yCYjO8/lY0yDV7iDzkT36twyvKZ/cMxC001RSNmtr3QNWWkRRDBWCSwnjW ++cn408gCVFPwVUOBwUr6aOeUY+fCcvWnYPCDj7ggdS5wEoUk+xrk4v2kU2gAH/mp +DqhFNouIcExoNW5j7j0w0YKnZtZJ9pviiM0EXS6vhk4ayxI2pi3VOqL2RhoNleAa +bTcCQ71wOxqpp4khssLcOsUR8trpadlvZJ9sc1ksUfoOz/pMI9Yj0IWctbuiriJp +l193X2sPzVMn3MaEt+XPrsX5wOogbQAfSJyY8pfCnZuhVLoZDpJADJxou0EhP+wH +p9yZc5GZosFgDJvTEhZfUmituLW4+op1FLJqA/LQSxBVz51OnmtzpgJLyR0ctTLG +9CcYbFTrzltPlOTHVjVW4rD9jyoLjLdfUf9qG65qVpGBisV+wD+SI6P0x5rhN7Dt +nC0YNZZ0cYyN24xw8Bxzcc9RkY8/MFfbTXOG43Uuh7fkPIdY2NQSUK2tkfiMdPgu +zlR1HoZHBrCcsQXJH0OhbuJ6Uwzm340Upj4b/eykq+uUcVY8PAUHSg6mwKy+E4yp +Za5Z5U50Kv9rFcE9Hwh09fGfdUrKTCFxoKrqfeW+ogTXJHQR5A41r9PP1l7/9Bp7 +P+UtdjJtAHzTO1r7/dckvghBslqhNBzA55wtWEmjMFh4Mm3lBMvBGrCelKPtaOrb +CYlv4eqGZMEeE3VoEKO3QnXU/dqJvhwQhjCcgxPtOzm9eSrofTvXa4xIMKyuNF2z +F6K0S5o3I+pBUInshXHWwN1pAT1R4FRYAUTv9mZbhLP+MWgPIMrdWWHAMDL5DeBH +G4AT5RQbzIHjQ12fJq30m1LajjLlL+mF5og+plMgEGOCJMHZyT2NcNb7gFHWk2mh +JmO/qxdXQ1FQ/oEf+gNmfgdlw/N6TY7PvmkVfdkhgp/zQLcGgJ33gj0gy4Jr284G +EhmeOGQflVsMFDqrAgjCEEJSLl/+FXuDfJjTixyly/yTTJCAeiEXsSW4xDisYZyR +dmEXPtx7eyelJjbsM2yMTNacvCA8TCywTqxYMlYF45kHhTrnQoMvx83U0vqB+ALA +JsGGrYQZ3tx9j8ae27b0rkSrccFYhKCXI/mwEZcZ6SG3q6/PhHWQOaie2EkuVLDq +YAK0ZjlTv0znE1OVN3ovKAqq8ga/y5tOKXREo/i/SRPj4aHel4Lky26+Nmm+t+E2 +CL3SBcqhBC45qIB27kdsqBsnCfSzm1fQsy6jivCEDneLTLNoltDyXunSwyLP/7HI +qclQDtLzvC0mHUNlhcds4I20 +-----END PRIVATE KEY----- diff --git a/test/openssl/fixtures/pkey/mldsa65-2.pem b/test/openssl/fixtures/pkey/mldsa65-2.pem new file mode 100644 index 0000000000..0ae64c2c5d --- /dev/null +++ b/test/openssl/fixtures/pkey/mldsa65-2.pem @@ -0,0 +1,88 @@ +-----BEGIN PRIVATE KEY----- +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 +qX4cmZjkE9fKw15cRjvQt1K1 +-----END PRIVATE KEY----- diff --git a/test/openssl/fixtures/pkey/rsa1024.pem b/test/openssl/fixtures/pkey/rsa1024.pem deleted file mode 100644 index 464de074be..0000000000 --- a/test/openssl/fixtures/pkey/rsa1024.pem +++ /dev/null @@ -1,15 +0,0 @@ ------BEGIN RSA PRIVATE KEY----- -MIICXgIBAAKBgQDLwsSw1ECnPtT+PkOgHhcGA71nwC2/nL85VBGnRqDxOqjVh7Cx -aKPERYHsk4BPCkE3brtThPWc9kjHEQQ7uf9Y1rbCz0layNqHyywQEVLFmp1cpIt/ -Q3geLv8ZD9pihowKJDyMDiN6ArYUmZczvW4976MU3+l54E6lF/JfFEU5hwIDAQAB -AoGBAKSl/MQarye1yOysqX6P8fDFQt68VvtXkNmlSiKOGuzyho0M+UVSFcs6k1L0 -maDE25AMZUiGzuWHyaU55d7RXDgeskDMakD1v6ZejYtxJkSXbETOTLDwUWTn618T -gnb17tU1jktUtU67xK/08i/XodlgnQhs6VoHTuCh3Hu77O6RAkEA7+gxqBuZR572 -74/akiW/SuXm0SXPEviyO1MuSRwtI87B02D0qgV8D1UHRm4AhMnJ8MCs1809kMQE -JiQUCrp9mQJBANlt2ngBO14us6NnhuAseFDTBzCHXwUUu1YKHpMMmxpnGqaldGgX -sOZB3lgJsT9VlGf3YGYdkLTNVbogQKlKpB8CQQDiSwkb4vyQfDe8/NpU5Not0fII -8jsDUCb+opWUTMmfbxWRR3FBNu8wnym/m19N4fFj8LqYzHX4KY0oVPu6qvJxAkEA -wa5snNekFcqONLIE4G5cosrIrb74sqL8GbGb+KuTAprzj5z1K8Bm0UW9lTjVDjDi -qRYgZfZSL+x1P/54+xTFSwJAY1FxA/N3QPCXCjPh5YqFxAMQs2VVYTfg+t0MEcJD -dPMQD5JX6g5HKnHFg2mZtoXQrWmJSn7p8GJK8yNTopEErA== ------END RSA PRIVATE KEY----- diff --git a/test/openssl/test_asn1.rb b/test/openssl/test_asn1.rb index 869ecc0635..5978ecf673 100644 --- a/test/openssl/test_asn1.rb +++ b/test/openssl/test_asn1.rb @@ -6,7 +6,7 @@ if defined?(OpenSSL) class OpenSSL::TestASN1 < OpenSSL::TestCase def test_decode_x509_certificate subj = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=TestCA") - key = Fixtures.pkey("rsa1024") + key = Fixtures.pkey("rsa-1") now = Time.at(Time.now.to_i) # suppress usec s = 0xdeadbeafdeadbeafdeadbeafdeadbeaf exts = [ @@ -306,7 +306,11 @@ class OpenSSL::TestASN1 < OpenSSL::TestCase end def test_object_identifier - encode_decode_test B(%w{ 06 01 00 }), OpenSSL::ASN1::ObjectId.new("0.0".b) + obj = encode_decode_test B(%w{ 06 01 00 }), OpenSSL::ASN1::ObjectId.new("0.0".b) + assert_equal "0.0", obj.oid + assert_nil obj.sn + assert_nil obj.ln + assert_equal obj.oid, obj.value encode_decode_test B(%w{ 06 01 28 }), OpenSSL::ASN1::ObjectId.new("1.0".b) encode_decode_test B(%w{ 06 03 88 37 03 }), OpenSSL::ASN1::ObjectId.new("2.999.3".b) encode_decode_test B(%w{ 06 05 2A 22 83 BB 55 }), OpenSSL::ASN1::ObjectId.new("1.2.34.56789".b) @@ -314,6 +318,7 @@ class OpenSSL::TestASN1 < OpenSSL::TestCase assert_equal "2.16.840.1.101.3.4.2.1", obj.oid assert_equal "SHA256", obj.sn assert_equal "sha256", obj.ln + assert_equal obj.sn, obj.value assert_raise(OpenSSL::ASN1::ASN1Error) { OpenSSL::ASN1.decode(B(%w{ 06 00 })) } @@ -389,6 +394,11 @@ class OpenSSL::TestASN1 < OpenSSL::TestCase ]) expected.indefinite_length = true encode_test B(%w{ 30 80 04 01 00 00 00 }), expected + + # Missing EOC at the end of contents octets + assert_raise(OpenSSL::ASN1::ASN1Error) { + OpenSSL::ASN1.decode(B(%w{ 30 80 01 01 FF })) + } end def test_set @@ -406,24 +416,38 @@ class OpenSSL::TestASN1 < OpenSSL::TestCase def test_utctime encode_decode_test B(%w{ 17 0D }) + "160908234339Z".b, OpenSSL::ASN1::UTCTime.new(Time.utc(2016, 9, 8, 23, 43, 39)) - begin - # possible range of UTCTime is 1969-2068 currently - encode_decode_test B(%w{ 17 0D }) + "690908234339Z".b, - OpenSSL::ASN1::UTCTime.new(Time.utc(1969, 9, 8, 23, 43, 39)) - rescue OpenSSL::ASN1::ASN1Error - pend "No negative time_t support?" - end - # not implemented + + # 1950-2049 range is assumed to match RFC 5280's expectation + encode_decode_test B(%w{ 17 0D }) + "490908234339Z".b, + OpenSSL::ASN1::UTCTime.new(Time.utc(2049, 9, 8, 23, 43, 39)) + encode_decode_test B(%w{ 17 0D }) + "500908234339Z".b, + OpenSSL::ASN1::UTCTime.new(Time.utc(1950, 9, 8, 23, 43, 39)) + assert_raise(OpenSSL::ASN1::ASN1Error) { + OpenSSL::ASN1::UTCTime.new(Time.new(2049, 12, 31, 23, 0, 0, "-04:00")).to_der + } + + # UTC offset (BER): ASN1_TIME_to_tm() may or may not support it # decode_test B(%w{ 17 11 }) + "500908234339+0930".b, # OpenSSL::ASN1::UTCTime.new(Time.new(1950, 9, 8, 23, 43, 39, "+09:30")) # decode_test B(%w{ 17 0F }) + "5009082343-0930".b, # OpenSSL::ASN1::UTCTime.new(Time.new(1950, 9, 8, 23, 43, 0, "-09:30")) - # assert_raise(OpenSSL::ASN1::ASN1Error) { - # OpenSSL::ASN1.decode(B(%w{ 17 0C }) + "500908234339".b) - # } - # assert_raise(OpenSSL::ASN1::ASN1Error) { - # OpenSSL::ASN1.decode(B(%w{ 17 0D }) + "500908234339Y".b) - # } + + # Seconds is omitted (BER) + # decode_test B(%w{ 18 0D }) + "201612081934Z".b, + # OpenSSL::ASN1::GeneralizedTime.new(Time.utc(2016, 12, 8, 19, 34, 0)) + + # Fractional seconds is not allowed in UTCTime + assert_raise(OpenSSL::ASN1::ASN1Error) { + OpenSSL::ASN1.decode(B(%w{ 17 0F }) + "160908234339.5Z".b) + } + + # Missing "Z" + assert_raise(OpenSSL::ASN1::ASN1Error) { + OpenSSL::ASN1.decode(B(%w{ 17 0C }) + "500908234339".b) + } + assert_raise(OpenSSL::ASN1::ASN1Error) { + OpenSSL::ASN1.decode(B(%w{ 17 0D }) + "500908234339Y".b) + } end def test_generalizedtime @@ -431,24 +455,46 @@ class OpenSSL::TestASN1 < OpenSSL::TestCase OpenSSL::ASN1::GeneralizedTime.new(Time.utc(2016, 12, 8, 19, 34, 29)) encode_decode_test B(%w{ 18 0F }) + "99990908234339Z".b, OpenSSL::ASN1::GeneralizedTime.new(Time.utc(9999, 9, 8, 23, 43, 39)) - # not implemented + + # Fractional seconds (DER). Not supported by ASN1_TIME_to_tm() + # because struct tm cannot store it. + # encode_decode_test B(%w{ 18 11 }) + "20161208193439.5Z".b, + # OpenSSL::ASN1::GeneralizedTime.new(Time.utc(2016, 12, 8, 19, 34, 39.5)) + + # UTC offset (BER): ASN1_TIME_to_tm() may or may not support it # decode_test B(%w{ 18 13 }) + "20161208193439+0930".b, # OpenSSL::ASN1::GeneralizedTime.new(Time.new(2016, 12, 8, 19, 34, 39, "+09:30")) # decode_test B(%w{ 18 11 }) + "201612081934-0930".b, # OpenSSL::ASN1::GeneralizedTime.new(Time.new(2016, 12, 8, 19, 34, 0, "-09:30")) # decode_test B(%w{ 18 11 }) + "201612081934-09".b, # OpenSSL::ASN1::GeneralizedTime.new(Time.new(2016, 12, 8, 19, 34, 0, "-09:00")) + + # Minutes and seconds are omitted (BER) + # decode_test B(%w{ 18 0B }) + "2016120819Z".b, + # OpenSSL::ASN1::GeneralizedTime.new(Time.utc(2016, 12, 8, 19, 0, 0)) + # Fractional hours (BER) # decode_test B(%w{ 18 0D }) + "2016120819.5Z".b, # OpenSSL::ASN1::GeneralizedTime.new(Time.utc(2016, 12, 8, 19, 30, 0)) + # Fractional hours with "," as the decimal separator (BER) # decode_test B(%w{ 18 0D }) + "2016120819,5Z".b, # OpenSSL::ASN1::GeneralizedTime.new(Time.utc(2016, 12, 8, 19, 30, 0)) + + # Seconds is omitted (BER) + # decode_test B(%w{ 18 0D }) + "201612081934Z".b, + # OpenSSL::ASN1::GeneralizedTime.new(Time.utc(2016, 12, 8, 19, 34, 0)) + # Fractional minutes (BER) # decode_test B(%w{ 18 0F }) + "201612081934.5Z".b, # OpenSSL::ASN1::GeneralizedTime.new(Time.utc(2016, 12, 8, 19, 34, 30)) - # decode_test B(%w{ 18 11 }) + "20161208193439.5Z".b, - # OpenSSL::ASN1::GeneralizedTime.new(Time.utc(2016, 12, 8, 19, 34, 39.5)) - # assert_raise(OpenSSL::ASN1::ASN1Error) { - # OpenSSL::ASN1.decode(B(%w{ 18 0D }) + "201612081934Y".b) - # } + + # Missing "Z" + assert_raise(OpenSSL::ASN1::ASN1Error) { + OpenSSL::ASN1.decode(B(%w{ 18 0F }) + "20161208193429Y".b) + } + + # Encoding year out of range + assert_raise(OpenSSL::ASN1::ASN1Error) { + OpenSSL::ASN1::GeneralizedTime.new(Time.utc(10000, 9, 8, 23, 43, 39)).to_der + } end def test_basic_asn1data diff --git a/test/openssl/test_bn.rb b/test/openssl/test_bn.rb index 5b68544574..f663102d45 100644 --- a/test/openssl/test_bn.rb +++ b/test/openssl/test_bn.rb @@ -345,29 +345,37 @@ class OpenSSL::TestBN < OpenSSL::TestCase assert_equal(4, e.get_flags(OpenSSL::BN::CONSTTIME)) end - if respond_to?(:ractor) + if defined?(Ractor) && respond_to?(:ractor) + unless Ractor.method_defined?(:value) # Ruby 3.4 or earlier + using Module.new { + refine Ractor do + alias value take + end + } + end + ractor def test_ractor - assert_equal(@e1, Ractor.new { OpenSSL::BN.new("999") }.take) - assert_equal(@e3, Ractor.new { OpenSSL::BN.new("\a\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF", 2) }.take) - assert_equal("999", Ractor.new(@e1) { |e1| e1.to_s }.take) - assert_equal("07FFFFFFFFFFFFFFFFFFFFFFFFFF", Ractor.new(@e3) { |e3| e3.to_s(16) }.take) - assert_equal(2**107-1, Ractor.new(@e3) { _1.to_i }.take) - assert_equal([1000, -999], Ractor.new(@e2) { _1.coerce(1000) }.take) - assert_equal(false, Ractor.new { 1.to_bn.zero? }.take) - assert_equal(true, Ractor.new { 1.to_bn.one? }.take) - assert_equal(true, Ractor.new(@e2) { _1.negative? }.take) - assert_equal("-03E7", Ractor.new(@e2) { _1.to_s(16) }.take) - assert_equal(2**107-1, Ractor.new(@e3) { _1.to_i }.take) - assert_equal([1000, -999], Ractor.new(@e2) { _1.coerce(1000) }.take) - assert_equal(true, Ractor.new { 0.to_bn.zero? }.take) - assert_equal(true, Ractor.new { 1.to_bn.one? }.take ) - assert_equal(false,Ractor.new { 2.to_bn.odd? }.take) - assert_equal(true, Ractor.new(@e2) { _1.negative? }.take) - assert_include(128..255, Ractor.new { OpenSSL::BN.rand(8)}.take) - assert_include(0...2**32, Ractor.new { OpenSSL::BN.generate_prime(32) }.take) + assert_equal(@e1, Ractor.new { OpenSSL::BN.new("999") }.value) + assert_equal(@e3, Ractor.new { OpenSSL::BN.new("\a\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF", 2) }.value) + assert_equal("999", Ractor.new(@e1) { |e1| e1.to_s }.value) + assert_equal("07FFFFFFFFFFFFFFFFFFFFFFFFFF", Ractor.new(@e3) { |e3| e3.to_s(16) }.value) + assert_equal(2**107-1, Ractor.new(@e3) { _1.to_i }.value) + assert_equal([1000, -999], Ractor.new(@e2) { _1.coerce(1000) }.value) + assert_equal(false, Ractor.new { 1.to_bn.zero? }.value) + assert_equal(true, Ractor.new { 1.to_bn.one? }.value) + assert_equal(true, Ractor.new(@e2) { _1.negative? }.value) + assert_equal("-03E7", Ractor.new(@e2) { _1.to_s(16) }.value) + assert_equal(2**107-1, Ractor.new(@e3) { _1.to_i }.value) + assert_equal([1000, -999], Ractor.new(@e2) { _1.coerce(1000) }.value) + assert_equal(true, Ractor.new { 0.to_bn.zero? }.value) + assert_equal(true, Ractor.new { 1.to_bn.one? }.value ) + assert_equal(false,Ractor.new { 2.to_bn.odd? }.value) + assert_equal(true, Ractor.new(@e2) { _1.negative? }.value) + assert_include(128..255, Ractor.new { OpenSSL::BN.rand(8)}.value) + assert_include(0...2**32, Ractor.new { OpenSSL::BN.generate_prime(32) }.value) if !aws_lc? # AWS-LC does not support BN::CONSTTIME. - assert_equal(0, Ractor.new { OpenSSL::BN.new(999).get_flags(OpenSSL::BN::CONSTTIME) }.take) + assert_equal(0, Ractor.new { OpenSSL::BN.new(999).get_flags(OpenSSL::BN::CONSTTIME) }.value) end # test if shareable when frozen assert Ractor.shareable?(@e1.freeze) diff --git a/test/openssl/test_cipher.rb b/test/openssl/test_cipher.rb index cd0b3dcb44..6a405da0a9 100644 --- a/test/openssl/test_cipher.rb +++ b/test/openssl/test_cipher.rb @@ -32,28 +32,28 @@ class OpenSSL::TestCipher < OpenSSL::TestCase salt = "\x01" * 8 num = 2048 pt = "data to be encrypted" - cipher = OpenSSL::Cipher.new("DES-EDE3-CBC").encrypt - cipher.pkcs5_keyivgen(pass, salt, num, "MD5") + cipher = OpenSSL::Cipher.new("AES-256-CBC").encrypt + cipher.pkcs5_keyivgen(pass, salt, num, "SHA256") s1 = cipher.update(pt) << cipher.final - d1 = num.times.inject(pass + salt) {|out, _| OpenSSL::Digest.digest('MD5', out) } - d2 = num.times.inject(d1 + pass + salt) {|out, _| OpenSSL::Digest.digest('MD5', out) } - key = (d1 + d2)[0, 24] - iv = (d1 + d2)[24, 8] - cipher = new_encryptor("DES-EDE3-CBC", key: key, iv: iv) + d1 = num.times.inject(pass + salt) {|out, _| OpenSSL::Digest.digest('SHA256', out) } + d2 = num.times.inject(d1 + pass + salt) {|out, _| OpenSSL::Digest.digest('SHA256', out) } + key = (d1 + d2)[0, 32] + iv = (d1 + d2)[32, 16] + cipher = new_encryptor("AES-256-CBC", key: key, iv: iv) s2 = cipher.update(pt) << cipher.final assert_equal s1, s2 - cipher2 = OpenSSL::Cipher.new("DES-EDE3-CBC").encrypt - assert_raise(ArgumentError) { cipher2.pkcs5_keyivgen(pass, salt, -1, "MD5") } + cipher2 = OpenSSL::Cipher.new("AES-256-CBC").encrypt + assert_raise(ArgumentError) { cipher2.pkcs5_keyivgen(pass, salt, -1, "SHA256") } end def test_info - cipher = OpenSSL::Cipher.new("DES-EDE3-CBC").encrypt - assert_equal "DES-EDE3-CBC", cipher.name - assert_equal 24, cipher.key_len - assert_equal 8, cipher.iv_len + cipher = OpenSSL::Cipher.new("AES-256-CBC").encrypt + assert_equal "AES-256-CBC", cipher.name + assert_equal 32, cipher.key_len + assert_equal 16, cipher.iv_len end def test_dup @@ -80,13 +80,13 @@ class OpenSSL::TestCipher < OpenSSL::TestCase end def test_key_iv_set - cipher = OpenSSL::Cipher.new("DES-EDE3-CBC").encrypt - assert_raise(ArgumentError) { cipher.key = "\x01" * 23 } - assert_nothing_raised { cipher.key = "\x01" * 24 } - assert_raise(ArgumentError) { cipher.key = "\x01" * 25 } - assert_raise(ArgumentError) { cipher.iv = "\x01" * 7 } - assert_nothing_raised { cipher.iv = "\x01" * 8 } - assert_raise(ArgumentError) { cipher.iv = "\x01" * 9 } + cipher = OpenSSL::Cipher.new("AES-256-CBC").encrypt + assert_raise(ArgumentError) { cipher.key = "\x01" * 31 } + assert_nothing_raised { cipher.key = "\x01" * 32 } + assert_raise(ArgumentError) { cipher.key = "\x01" * 33 } + assert_raise(ArgumentError) { cipher.iv = "\x01" * 15 } + assert_nothing_raised { cipher.iv = "\x01" * 16 } + assert_raise(ArgumentError) { cipher.iv = "\x01" * 17 } end def test_random_key_iv @@ -109,9 +109,12 @@ class OpenSSL::TestCipher < OpenSSL::TestCase end def test_initialize - cipher = OpenSSL::Cipher.new("DES-EDE3-CBC") - assert_raise(RuntimeError) { cipher.__send__(:initialize, "DES-EDE3-CBC") } + cipher = OpenSSL::Cipher.new("AES-256-CBC") + assert_raise(RuntimeError) { cipher.__send__(:initialize, "AES-256-CBC") } assert_raise(RuntimeError) { OpenSSL::Cipher.allocate.final } + assert_raise(OpenSSL::Cipher::CipherError) { + OpenSSL::Cipher.new("no such algorithm") + } end def test_ctr_if_exists @@ -131,13 +134,14 @@ class OpenSSL::TestCipher < OpenSSL::TestCase def test_update_with_buffer cipher = OpenSSL::Cipher.new("aes-128-ecb").encrypt cipher.random_key - expected = cipher.update("data") << cipher.final - assert_equal 16, expected.bytesize + expected = cipher.update("data" * 10) << cipher.final + assert_equal 48, expected.bytesize # Buffer is supplied cipher.reset buf = String.new - assert_same buf, cipher.update("data", buf) + assert_same buf, cipher.update("data" * 10, buf) + assert_equal 32, buf.bytesize assert_equal expected, buf + cipher.final # Buffer is frozen @@ -146,9 +150,9 @@ class OpenSSL::TestCipher < OpenSSL::TestCase # Buffer is a shared string [ruby-core:120141] [Bug #20937] cipher.reset - buf = "x" * 1024 - shared = buf[-("data".bytesize + 32)..-1] - assert_same shared, cipher.update("data", shared) + buf = "x".b * 1024 + shared = buf[-("data".bytesize * 10 + 32)..-1] + assert_same shared, cipher.update("data" * 10, shared) assert_equal expected, shared + cipher.final end @@ -165,12 +169,12 @@ class OpenSSL::TestCipher < OpenSSL::TestCase %w(ecb cbc cfb ofb).each{|mode| c1 = OpenSSL::Cipher.new("aes-256-#{mode}") c1.encrypt - c1.pkcs5_keyivgen("passwd") + c1.pkcs5_keyivgen("passwd", "12345678", 10000, "SHA256") ct = c1.update(pt) + c1.final c2 = OpenSSL::Cipher.new("aes-256-#{mode}") c2.decrypt - c2.pkcs5_keyivgen("passwd") + c2.pkcs5_keyivgen("passwd", "12345678", 10000, "SHA256") assert_equal(pt, c2.update(ct) + c2.final) } end @@ -182,6 +186,10 @@ class OpenSSL::TestCipher < OpenSSL::TestCase end end + def test_auth_tag_error_inheritance + assert_equal OpenSSL::Cipher::CipherError, OpenSSL::Cipher::AuthTagError.superclass + end + def test_authenticated cipher = OpenSSL::Cipher.new('aes-128-gcm') assert_predicate(cipher, :authenticated?) @@ -212,7 +220,8 @@ class OpenSSL::TestCipher < OpenSSL::TestCase cipher = new_decryptor("aes-128-ccm", **kwargs, ccm_data_len: ct.length, auth_tag: tag[0, 8], auth_data: aad) assert_equal pt, cipher.update(ct) << cipher.final - # wrong tag is rejected + # wrong tag is rejected - in CCM, authentication happens during update, but + # we consider this a general CipherError since update failures can have various causes tag2 = tag.dup tag2.setbyte(-1, (tag2.getbyte(-1) + 1) & 0xff) cipher = new_decryptor("aes-128-ccm", **kwargs, ccm_data_len: ct.length, auth_tag: tag2, auth_data: aad) @@ -265,19 +274,19 @@ class OpenSSL::TestCipher < OpenSSL::TestCase tag2.setbyte(-1, (tag2.getbyte(-1) + 1) & 0xff) cipher = new_decryptor("aes-128-gcm", key: key, iv: iv, auth_tag: tag2, auth_data: aad) cipher.update(ct) - assert_raise(OpenSSL::Cipher::CipherError) { cipher.final } + assert_raise(OpenSSL::Cipher::AuthTagError) { cipher.final } # wrong aad is rejected aad2 = aad[0..-2] << aad[-1].succ cipher = new_decryptor("aes-128-gcm", key: key, iv: iv, auth_tag: tag, auth_data: aad2) cipher.update(ct) - assert_raise(OpenSSL::Cipher::CipherError) { cipher.final } + assert_raise(OpenSSL::Cipher::AuthTagError) { cipher.final } # wrong ciphertext is rejected ct2 = ct[0..-2] << ct[-1].succ cipher = new_decryptor("aes-128-gcm", key: key, iv: iv, auth_tag: tag, auth_data: aad) cipher.update(ct2) - assert_raise(OpenSSL::Cipher::CipherError) { cipher.final } + assert_raise(OpenSSL::Cipher::AuthTagError) { cipher.final } end def test_aes_gcm_variable_iv_len @@ -304,6 +313,9 @@ class OpenSSL::TestCipher < OpenSSL::TestCase end def test_aes_ocb_tag_len + # AES-128-OCB is not FIPS-approved. + omit_on_fips + # RFC 7253 Appendix A; the second sample key = ["000102030405060708090A0B0C0D0E0F"].pack("H*") iv = ["BBAA99887766554433221101"].pack("H*") @@ -337,6 +349,27 @@ class OpenSSL::TestCipher < OpenSSL::TestCase end if has_cipher?("aes-128-ocb") + def test_aes_gcm_siv + # AES-128-GCM-SIV is not FIPS-approved. + omit_on_fips + + # RFC 8452 Appendix C.1., 8th example + key = ["01000000000000000000000000000000"].pack("H*") + iv = ["030000000000000000000000"].pack("H*") + aad = ["01"].pack("H*") + pt = ["0200000000000000"].pack("H*") + ct = ["1e6daba35669f4273b0a1a2560969cdf790d99759abd1508"].pack("H*") + tag = ["3b0a1a2560969cdf790d99759abd1508"].pack("H*") + ct_without_tag = ct.byteslice(0, ct.bytesize - tag.bytesize) + + cipher = new_encryptor("aes-128-gcm-siv", key: key, iv: iv, auth_data: aad) + assert_equal ct_without_tag, cipher.update(pt) << cipher.final + assert_equal tag, cipher.auth_tag + cipher = new_decryptor("aes-128-gcm-siv", key: key, iv: iv, auth_tag: tag, + auth_data: aad) + assert_equal pt, cipher.update(ct_without_tag) << cipher.final + end if openssl?(3, 2, 0) + def test_aes_gcm_key_iv_order_issue pt = "[ruby/openssl#49]" cipher = OpenSSL::Cipher.new("aes-128-gcm").encrypt @@ -363,7 +396,7 @@ class OpenSSL::TestCipher < OpenSSL::TestCase begin cipher = OpenSSL::Cipher.new("id-aes192-wrap-pad").encrypt - rescue OpenSSL::Cipher::CipherError, RuntimeError + rescue OpenSSL::Cipher::CipherError omit "id-aes192-wrap-pad is not supported: #$!" end cipher.key = kek diff --git a/test/openssl/test_digest.rb b/test/openssl/test_digest.rb index 5b4eb3c74c..bc1f680df5 100644 --- a/test/openssl/test_digest.rb +++ b/test/openssl/test_digest.rb @@ -6,23 +6,31 @@ if defined?(OpenSSL) class OpenSSL::TestDigest < OpenSSL::TestCase def setup super - @d1 = OpenSSL::Digest.new("MD5") - @d2 = OpenSSL::Digest::MD5.new + @d1 = OpenSSL::Digest.new("SHA256") + @d2 = OpenSSL::Digest::SHA256.new + end + + def test_initialize + assert_raise(OpenSSL::Digest::DigestError) { + OpenSSL::Digest.new("no such algorithm") + } end def test_digest - null_hex = "d41d8cd98f00b204e9800998ecf8427e" + # SHA256 null value calculated by `echo -n "" | sha256sum` + null_hex = "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" null_bin = [null_hex].pack("H*") data = "DATA" - hex = "e44f9e348e41cb272efa87387728571b" + # SHA256 DATA value calculated by `echo -n "DATA" | sha256sum` + hex = "c97c29c7a71b392b437ee03fd17f09bb10b75e879466fc0eb757b2c4a78ac938" bin = [hex].pack("H*") assert_equal(null_bin, @d1.digest) assert_equal(null_hex, @d1.hexdigest) @d1 << data assert_equal(bin, @d1.digest) assert_equal(hex, @d1.hexdigest) - assert_equal(bin, OpenSSL::Digest.digest('MD5', data)) - assert_equal(hex, OpenSSL::Digest.hexdigest('MD5', data)) + assert_equal(bin, OpenSSL::Digest.digest('SHA256', data)) + assert_equal(hex, OpenSSL::Digest.hexdigest('SHA256', data)) end def test_eql @@ -32,9 +40,9 @@ class OpenSSL::TestDigest < OpenSSL::TestCase end def test_info - assert_equal("MD5", @d1.name, "name") - assert_equal("MD5", @d2.name, "name") - assert_equal(16, @d1.size, "size") + assert_equal("SHA256", @d1.name, "name") + assert_equal("SHA256", @d2.name, "name") + assert_equal(32, @d1.size, "size") end def test_dup @@ -54,7 +62,10 @@ class OpenSSL::TestDigest < OpenSSL::TestCase end def test_digest_constants - %w{MD5 SHA1 SHA224 SHA256 SHA384 SHA512}.each do |name| + non_fips_names = %w{MD5} + names = %w{SHA1 SHA224 SHA256 SHA384 SHA512} + names = non_fips_names + names unless OpenSSL.fips_mode + names.each do |name| assert_not_nil(OpenSSL::Digest.new(name)) klass = OpenSSL::Digest.const_get(name.tr('-', '_')) assert_not_nil(klass.new) @@ -62,8 +73,17 @@ class OpenSSL::TestDigest < OpenSSL::TestCase end def test_digest_by_oid_and_name - check_digest(OpenSSL::ASN1::ObjectId.new("MD5")) - check_digest(OpenSSL::ASN1::ObjectId.new("SHA1")) + # SHA256 + o1 = OpenSSL::Digest.digest("SHA256", "") + o2 = OpenSSL::Digest.digest("sha256", "") + assert_equal(o1, o2) + o3 = OpenSSL::Digest.digest("2.16.840.1.101.3.4.2.1", "") + assert_equal(o1, o3) + + # An alias for SHA256 recognized by EVP_get_digestbyname(), but not by + # EVP_MD_fetch() + o4 = OpenSSL::Digest.digest("RSA-SHA256", "") + assert_equal(o1, o4) end def encode16(str) @@ -109,12 +129,15 @@ class OpenSSL::TestDigest < OpenSSL::TestCase assert_equal(s512, OpenSSL::Digest.hexdigest('SHA3-512', "")) end - def test_digest_by_oid_and_name_sha2 - check_digest(OpenSSL::ASN1::ObjectId.new("SHA224")) - check_digest(OpenSSL::ASN1::ObjectId.new("SHA256")) - check_digest(OpenSSL::ASN1::ObjectId.new("SHA384")) - check_digest(OpenSSL::ASN1::ObjectId.new("SHA512")) - end + def test_fetched_evp_md + # KECCAK-256 is not FIPS-approved. + omit_on_fips + + # Pre-NIST Keccak is an example of a digest algorithm that doesn't have an + # NID and requires dynamic allocation of EVP_MD + hex = "c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470" + assert_equal(hex, OpenSSL::Digest.hexdigest("KECCAK-256", "")) + end if openssl?(3, 2, 0) def test_openssl_digest assert_equal OpenSSL::Digest::MD5, OpenSSL::Digest("MD5") @@ -133,15 +156,20 @@ class OpenSSL::TestDigest < OpenSSL::TestCase assert_include digests, "sha512" end - private + if respond_to?(:ractor) && defined?(Ractor.shareable_proc) + ractor - def check_digest(oid) - d = OpenSSL::Digest.new(oid.sn) - assert_not_nil(d) - d = OpenSSL::Digest.new(oid.ln) - assert_not_nil(d) - d = OpenSSL::Digest.new(oid.oid) - assert_not_nil(d) + def test_ractor + assert_nothing_raised do + Ractor.new { + [ + OpenSSL::Digest::SHA256.new(""), + OpenSSL::Digest::SHA256.hexdigest(""), + OpenSSL::Digest::SHA256.digest(""), + ] + }.value + end + end end end diff --git a/test/openssl/test_fips.rb b/test/openssl/test_fips.rb index efc2655e25..683e0011e8 100644 --- a/test/openssl/test_fips.rb +++ b/test/openssl/test_fips.rb @@ -30,7 +30,7 @@ class OpenSSL::TestFIPS < OpenSSL::TestCase def test_fips_mode_is_reentrant return if aws_lc? # AWS-LC's FIPS mode is decided at compile time. - assert_separately(["-ropenssl"], <<~"end;") + assert_ruby_status(["-ropenssl"], <<~"end;") OpenSSL.fips_mode = false OpenSSL.fips_mode = false end; diff --git a/test/openssl/test_hmac.rb b/test/openssl/test_hmac.rb index 3cb707448a..7cf820628e 100644 --- a/test/openssl/test_hmac.rb +++ b/test/openssl/test_hmac.rb @@ -4,14 +4,18 @@ require_relative 'utils' if defined?(OpenSSL) class OpenSSL::TestHMAC < OpenSSL::TestCase - def test_hmac + def test_hmac_md5 + omit_on_fips # MD5 + # RFC 2202 2. Test Cases for HMAC-MD5 hmac = OpenSSL::HMAC.new(["0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b"].pack("H*"), "MD5") hmac.update("Hi There") assert_equal ["9294727a3638bb1c13f48ef8158bfc9d"].pack("H*"), hmac.digest assert_equal "9294727a3638bb1c13f48ef8158bfc9d", hmac.hexdigest assert_equal "kpRyejY4uxwT9I74FYv8nQ==", hmac.base64digest + end + def test_hmac_sha224 # RFC 4231 4.2. Test Case 1 hmac = OpenSSL::HMAC.new(["0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b"].pack("H*"), "SHA224") hmac.update("Hi There") @@ -21,7 +25,7 @@ class OpenSSL::TestHMAC < OpenSSL::TestCase end def test_dup - h1 = OpenSSL::HMAC.new("KEY", "MD5") + h1 = OpenSSL::HMAC.new("KEY"*32, "SHA256") h1.update("DATA") h = h1.dup assert_equal(h1.digest, h.digest, "dup digest") @@ -35,7 +39,7 @@ class OpenSSL::TestHMAC < OpenSSL::TestCase end def test_reset_keep_key - h1 = OpenSSL::HMAC.new("KEY", "MD5") + h1 = OpenSSL::HMAC.new("KEY"*32, "SHA256") first = h1.update("test").hexdigest h1.reset second = h1.update("test").hexdigest @@ -43,9 +47,9 @@ class OpenSSL::TestHMAC < OpenSSL::TestCase end def test_eq - h1 = OpenSSL::HMAC.new("KEY", "MD5") - h2 = OpenSSL::HMAC.new("KEY", OpenSSL::Digest.new("MD5")) - h3 = OpenSSL::HMAC.new("FOO", "MD5") + h1 = OpenSSL::HMAC.new("KEY"*32, "SHA256") + h2 = OpenSSL::HMAC.new("KEY"*32, OpenSSL::Digest.new("SHA256")) + h3 = OpenSSL::HMAC.new("FOO"*32, "SHA256") assert_equal h1, h2 refute_equal h1, h2.digest @@ -53,17 +57,19 @@ class OpenSSL::TestHMAC < OpenSSL::TestCase end def test_singleton_methods - # RFC 2202 2. Test Cases for HMAC-MD5 - key = ["0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b"].pack("H*") - digest = OpenSSL::HMAC.digest("MD5", key, "Hi There") - assert_equal ["9294727a3638bb1c13f48ef8158bfc9d"].pack("H*"), digest - hexdigest = OpenSSL::HMAC.hexdigest("MD5", key, "Hi There") - assert_equal "9294727a3638bb1c13f48ef8158bfc9d", hexdigest - b64digest = OpenSSL::HMAC.base64digest("MD5", key, "Hi There") - assert_equal "kpRyejY4uxwT9I74FYv8nQ==", b64digest + # RFC 4231 4.2. Test Case 1 + key = ["0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b"].pack("H*") + digest = OpenSSL::HMAC.digest("SHA256", key, "Hi There") + assert_equal ["b0344c61d8db38535ca8afceaf0bf12b881dc200c9833da726e9376c2e32cff7"].pack("H*"), digest + hexdigest = OpenSSL::HMAC.hexdigest("SHA256", key, "Hi There") + assert_equal "b0344c61d8db38535ca8afceaf0bf12b881dc200c9833da726e9376c2e32cff7", hexdigest + b64digest = OpenSSL::HMAC.base64digest("SHA256", key, "Hi There") + assert_equal "sDRMYdjbOFNcqK/OrwvxK4gdwgDJgz2nJuk3bC4yz/c=", b64digest end def test_zero_length_key + omit_on_fips # Key length + # Empty string as the key hexdigest = OpenSSL::HMAC.hexdigest("SHA256", "\0"*32, "test") assert_equal "43b0cef99265f9e34c10ea9d3501926d27b39f57c6d674561d8ba236e7a819fb", hexdigest diff --git a/test/openssl/test_kdf.rb b/test/openssl/test_kdf.rb index 6a12a25aa8..708d1883af 100644 --- a/test/openssl/test_kdf.rb +++ b/test/openssl/test_kdf.rb @@ -5,64 +5,31 @@ if defined?(OpenSSL) class OpenSSL::TestKDF < OpenSSL::TestCase def test_pkcs5_pbkdf2_hmac_compatibility - expected = OpenSSL::KDF.pbkdf2_hmac("password", salt: "salt", iterations: 1, length: 20, hash: "sha1") - assert_equal(expected, OpenSSL::PKCS5.pbkdf2_hmac("password", "salt", 1, 20, "sha1")) - assert_equal(expected, OpenSSL::PKCS5.pbkdf2_hmac_sha1("password", "salt", 1, 20)) + # PBKDF2 salt >= 16 bytes (128 bits) and iterations >= 1000 are required in + # FIPS. + # SP 800-132. + # https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-132.pdf + # * 5.1 The Salt (S) + # * 5.2 The Iteration Count (C) + # https://github.com/openssl/openssl/blob/71943544885ff364a10bcc5ffc62d0e651c9a021/providers/implementations/kdfs/pbkdf2.c#L235-L240 + # https://github.com/openssl/openssl/blob/71943544885ff364a10bcc5ffc62d0e651c9a021/providers/implementations/kdfs/pbkdf2.c#L247-L252 + # Use the same parameters with test_pbkdf2_hmac_sha1_rfc6070_c_4096_len_25. + expected = OpenSSL::KDF.pbkdf2_hmac("passwordPASSWORDpassword", + salt: "saltSALTsaltSALTsaltSALTsaltSALTsalt", + iterations: 4096, + length: 25, + hash: "sha1") + assert_equal(expected, OpenSSL::PKCS5.pbkdf2_hmac("passwordPASSWORDpassword", + "saltSALTsaltSALTsaltSALTsaltSALTsalt", + 4096, + 25, + "sha1")) + assert_equal(expected, OpenSSL::PKCS5.pbkdf2_hmac_sha1("passwordPASSWORDpassword", + "saltSALTsaltSALTsaltSALTsaltSALTsalt", + 4096, + 25)) end - def test_pbkdf2_hmac_sha1_rfc6070_c_1_len_20 - p ="password" - s = "salt" - c = 1 - dk_len = 20 - raw = %w{ 0c 60 c8 0f 96 1f 0e 71 - f3 a9 b5 24 af 60 12 06 - 2f e0 37 a6 } - expected = [raw.join('')].pack('H*') - value = OpenSSL::KDF.pbkdf2_hmac(p, salt: s, iterations: c, length: dk_len, hash: "sha1") - assert_equal(expected, value) - end - - def test_pbkdf2_hmac_sha1_rfc6070_c_2_len_20 - p ="password" - s = "salt" - c = 2 - dk_len = 20 - raw = %w{ ea 6c 01 4d c7 2d 6f 8c - cd 1e d9 2a ce 1d 41 f0 - d8 de 89 57 } - expected = [raw.join('')].pack('H*') - value = OpenSSL::KDF.pbkdf2_hmac(p, salt: s, iterations: c, length: dk_len, hash: "sha1") - assert_equal(expected, value) - end - - def test_pbkdf2_hmac_sha1_rfc6070_c_4096_len_20 - p ="password" - s = "salt" - c = 4096 - dk_len = 20 - raw = %w{ 4b 00 79 01 b7 65 48 9a - be ad 49 d9 26 f7 21 d0 - 65 a4 29 c1 } - expected = [raw.join('')].pack('H*') - value = OpenSSL::KDF.pbkdf2_hmac(p, salt: s, iterations: c, length: dk_len, hash: "sha1") - assert_equal(expected, value) - end - -# takes too long! -# def test_pbkdf2_hmac_sha1_rfc6070_c_16777216_len_20 -# p ="password" -# s = "salt" -# c = 16777216 -# dk_len = 20 -# raw = %w{ ee fe 3d 61 cd 4d a4 e4 -# e9 94 5b 3d 6b a2 15 8c -# 26 34 e9 84 } -# expected = [raw.join('')].pack('H*') -# value = OpenSSL::KDF.pbkdf2_hmac(p, salt: s, iterations: c, length: dk_len, hash: "sha1") -# assert_equal(expected, value) -# end - def test_pbkdf2_hmac_sha1_rfc6070_c_4096_len_25 p ="passwordPASSWORDpassword" s = "saltSALTsaltSALTsaltSALTsaltSALTsalt" @@ -78,18 +45,6 @@ class OpenSSL::TestKDF < OpenSSL::TestCase assert_equal(expected, value) end - def test_pbkdf2_hmac_sha1_rfc6070_c_4096_len_16 - p ="pass\0word" - s = "sa\0lt" - c = 4096 - dk_len = 16 - raw = %w{ 56 fa 6a a7 55 48 09 9d - cc 37 d7 f0 34 25 e0 c3 } - expected = [raw.join('')].pack('H*') - value = OpenSSL::KDF.pbkdf2_hmac(p, salt: s, iterations: c, length: dk_len, hash: "sha1") - assert_equal(expected, value) - end - def test_pbkdf2_hmac_sha256_c_20000_len_32 #unfortunately no official test vectors available yet for SHA-2 p ="password" @@ -103,6 +58,11 @@ class OpenSSL::TestKDF < OpenSSL::TestCase def test_scrypt_rfc7914_first pend "scrypt is not implemented" unless OpenSSL::KDF.respond_to?(:scrypt) # OpenSSL >= 1.1.0 + # scrypt is not available in FIPS. + # EVP_KDF_fetch(ctx, OSSL_KDF_NAME_SCRYPT, propq) returns NULL in FIPS. + # https://github.com/openssl/openssl/blob/71943544885ff364a10bcc5ffc62d0e651c9a021/crypto/evp/pbe_scrypt.c#L67-L71 + omit_on_fips + pass = "" salt = "" n = 16 @@ -118,6 +78,9 @@ class OpenSSL::TestKDF < OpenSSL::TestCase def test_scrypt_rfc7914_second pend "scrypt is not implemented" unless OpenSSL::KDF.respond_to?(:scrypt) # OpenSSL >= 1.1.0 + # scrypt is not available in FIPS. + omit_on_fips + pass = "password" salt = "NaCl" n = 1024 @@ -131,6 +94,7 @@ class OpenSSL::TestKDF < OpenSSL::TestCase assert_equal(expected, OpenSSL::KDF.scrypt(pass, salt: salt, N: n, r: r, p: p, length: dklen)) end + # https://www.rfc-editor.org/rfc/rfc5869#appendix-A.1 def test_hkdf_rfc5869_test_case_1 hash = "sha256" ikm = B("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b") @@ -144,6 +108,7 @@ class OpenSSL::TestKDF < OpenSSL::TestCase assert_equal(okm, OpenSSL::KDF.hkdf(ikm, salt: salt, info: info, length: l, hash: hash)) end + # https://www.rfc-editor.org/rfc/rfc5869#appendix-A.3 def test_hkdf_rfc5869_test_case_3 hash = "sha256" ikm = B("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b") @@ -157,16 +122,32 @@ class OpenSSL::TestKDF < OpenSSL::TestCase assert_equal(okm, OpenSSL::KDF.hkdf(ikm, salt: salt, info: info, length: l, hash: hash)) end - def test_hkdf_rfc5869_test_case_4 + # https://www.rfc-editor.org/rfc/rfc5869#appendix-A.5 + def test_hkdf_rfc5869_test_case_5 hash = "sha1" - ikm = B("0b0b0b0b0b0b0b0b0b0b0b") - salt = B("000102030405060708090a0b0c") - info = B("f0f1f2f3f4f5f6f7f8f9") - l = 42 - - okm = B("085a01ea1b10f36933068b56efa5ad81" \ - "a4f14b822f5b091568a9cdd4f155fda2" \ - "c22e422478d305f3f896") + ikm = B("000102030405060708090a0b0c0d0e0f" \ + "101112131415161718191a1b1c1d1e1f" \ + "202122232425262728292a2b2c2d2e2f" \ + "303132333435363738393a3b3c3d3e3f" \ + "404142434445464748494a4b4c4d4e4f") + salt = B("606162636465666768696a6b6c6d6e6f" \ + "707172737475767778797a7b7c7d7e7f" \ + "808182838485868788898a8b8c8d8e8f" \ + "909192939495969798999a9b9c9d9e9f" \ + "a0a1a2a3a4a5a6a7a8a9aaabacadaeaf") + info = B("b0b1b2b3b4b5b6b7b8b9babbbcbdbebf" \ + "c0c1c2c3c4c5c6c7c8c9cacbcccdcecf" \ + "d0d1d2d3d4d5d6d7d8d9dadbdcdddedf" \ + "e0e1e2e3e4e5e6e7e8e9eaebecedeeef" \ + "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff") + l = 82 + + okm = B("0bd770a74d1160f7c9f12cd5912a06eb" \ + "ff6adcae899d92191fe4305673ba2ffe" \ + "8fa3f1a4e5ad79f3f334b3b202b2173c" \ + "486ea37ce3d397ed034c7f9dfeb15c5e" \ + "927336d0441f4c4300e2cff0d0900b52" \ + "d3b4") assert_equal(okm, OpenSSL::KDF.hkdf(ikm, salt: salt, info: info, length: l, hash: hash)) end diff --git a/test/openssl/test_ns_spki.rb b/test/openssl/test_ns_spki.rb index d76fc9e5cf..0484429289 100644 --- a/test/openssl/test_ns_spki.rb +++ b/test/openssl/test_ns_spki.rb @@ -17,8 +17,8 @@ class OpenSSL::TestNSSPI < OpenSSL::TestCase end def test_build_data - key1 = Fixtures.pkey("rsa1024") - key2 = Fixtures.pkey("rsa2048") + key1 = Fixtures.pkey("rsa-1") + key2 = Fixtures.pkey("rsa-2") spki = OpenSSL::Netscape::SPKI.new spki.challenge = "RandomString" spki.public_key = key1.public_key diff --git a/test/openssl/test_ocsp.rb b/test/openssl/test_ocsp.rb index cf96fc22e5..c43ff5cb55 100644 --- a/test/openssl/test_ocsp.rb +++ b/test/openssl/test_ocsp.rb @@ -13,7 +13,7 @@ class OpenSSL::TestOCSP < OpenSSL::TestCase # @cert2 @ocsp_cert ca_subj = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=TestCA") - @ca_key = Fixtures.pkey("rsa1024") + @ca_key = Fixtures.pkey("rsa-1") ca_exts = [ ["basicConstraints", "CA:TRUE", true], ["keyUsage", "cRLSign,keyCertSign", true], @@ -22,7 +22,7 @@ class OpenSSL::TestOCSP < OpenSSL::TestCase ca_subj, @ca_key, 1, ca_exts, nil, nil) cert_subj = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=TestCA2") - @cert_key = Fixtures.pkey("rsa1024") + @cert_key = Fixtures.pkey("rsa-2") cert_exts = [ ["basicConstraints", "CA:TRUE", true], ["keyUsage", "cRLSign,keyCertSign", true], @@ -31,14 +31,14 @@ class OpenSSL::TestOCSP < OpenSSL::TestCase cert_subj, @cert_key, 5, cert_exts, @ca_cert, @ca_key) cert2_subj = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=TestCert") - @cert2_key = Fixtures.pkey("rsa1024") + @cert2_key = Fixtures.pkey("rsa-3") cert2_exts = [ ] @cert2 = OpenSSL::TestUtils.issue_cert( cert2_subj, @cert2_key, 10, cert2_exts, @cert, @cert_key) ocsp_subj = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=TestCAOCSP") - @ocsp_key = Fixtures.pkey("rsa2048") + @ocsp_key = Fixtures.pkey("p256") ocsp_exts = [ ["extendedKeyUsage", "OCSPSigning", true], ] @@ -63,8 +63,10 @@ class OpenSSL::TestOCSP < OpenSSL::TestCase def test_certificate_id_issuer_key_hash cid = OpenSSL::OCSP::CertificateId.new(@cert, @ca_cert) - assert_equal OpenSSL::Digest.hexdigest('SHA1', OpenSSL::ASN1.decode(@ca_cert.to_der).value[0].value[6].value[1].value), cid.issuer_key_hash - assert_equal "d1fef9fbf8ae1bc160cbfa03e2596dd873089213", cid.issuer_key_hash + # content of subjectPublicKey (bit string) in SubjectPublicKeyInfo + spki = OpenSSL::ASN1.decode(@ca_key.public_to_der) + assert_equal OpenSSL::Digest.hexdigest("SHA1", spki.value[1].value), + cid.issuer_key_hash end def test_certificate_id_hash_algorithm @@ -213,6 +215,35 @@ class OpenSSL::TestOCSP < OpenSSL::TestCase assert_equal bres.to_der, bres.dup.to_der end + def test_basic_response_status_good + bres = OpenSSL::OCSP::BasicResponse.new + cid = OpenSSL::OCSP::CertificateId.new(@cert, @ca_cert, OpenSSL::Digest.new('SHA1')) + bres.add_status(cid, OpenSSL::OCSP::V_CERTSTATUS_GOOD, 0, nil, -300, 500, nil) + bres.sign(@ocsp_cert, @ocsp_key, [@ca_cert]) + + statuses = bres.status + assert_equal 1, statuses.size + status = statuses[0] + assert_equal cid.to_der, status[0].to_der + assert_equal OpenSSL::OCSP::V_CERTSTATUS_GOOD, status[1] + assert_nil status[3] # revtime should be nil for GOOD status + end + + def test_basic_response_status_revoked + bres = OpenSSL::OCSP::BasicResponse.new + now = Time.at(Time.now.to_i) + cid = OpenSSL::OCSP::CertificateId.new(@cert, @ca_cert, OpenSSL::Digest.new('SHA1')) + bres.add_status(cid, OpenSSL::OCSP::V_CERTSTATUS_REVOKED, + OpenSSL::OCSP::REVOKED_STATUS_UNSPECIFIED, now - 400, -300, nil, nil) + bres.sign(@ocsp_cert, @ocsp_key, [@ca_cert]) + + statuses = bres.status + assert_equal 1, statuses.size + status = statuses[0] + assert_equal OpenSSL::OCSP::V_CERTSTATUS_REVOKED, status[1] + assert_equal now - 400, status[3] # revtime should be the revocation time + end + def test_basic_response_response_operations bres = OpenSSL::OCSP::BasicResponse.new now = Time.at(Time.now.to_i) diff --git a/test/openssl/test_ossl.rb b/test/openssl/test_ossl.rb index 9f4b39d4f5..1b9bde53ef 100644 --- a/test/openssl/test_ossl.rb +++ b/test/openssl/test_ossl.rb @@ -3,42 +3,52 @@ require_relative "utils" if defined?(OpenSSL) -class OpenSSL::OSSL < OpenSSL::SSLTestCase +class OpenSSL::TestOSSL < OpenSSL::TestCase def test_fixed_length_secure_compare assert_raise(ArgumentError) { OpenSSL.fixed_length_secure_compare("aaa", "a") } assert_raise(ArgumentError) { OpenSSL.fixed_length_secure_compare("aaa", "aa") } - assert OpenSSL.fixed_length_secure_compare("aaa", "aaa") - assert OpenSSL.fixed_length_secure_compare( + assert_true(OpenSSL.fixed_length_secure_compare("aaa", "aaa")) + assert_true(OpenSSL.fixed_length_secure_compare( OpenSSL::Digest.digest('SHA256', "aaa"), OpenSSL::Digest::SHA256.digest("aaa") - ) + )) assert_raise(ArgumentError) { OpenSSL.fixed_length_secure_compare("aaa", "aaaa") } - refute OpenSSL.fixed_length_secure_compare("aaa", "baa") - refute OpenSSL.fixed_length_secure_compare("aaa", "aba") - refute OpenSSL.fixed_length_secure_compare("aaa", "aab") + assert_false(OpenSSL.fixed_length_secure_compare("aaa", "baa")) + assert_false(OpenSSL.fixed_length_secure_compare("aaa", "aba")) + assert_false(OpenSSL.fixed_length_secure_compare("aaa", "aab")) assert_raise(ArgumentError) { OpenSSL.fixed_length_secure_compare("aaa", "aaab") } assert_raise(ArgumentError) { OpenSSL.fixed_length_secure_compare("aaa", "b") } assert_raise(ArgumentError) { OpenSSL.fixed_length_secure_compare("aaa", "bb") } - refute OpenSSL.fixed_length_secure_compare("aaa", "bbb") + assert_false(OpenSSL.fixed_length_secure_compare("aaa", "bbb")) assert_raise(ArgumentError) { OpenSSL.fixed_length_secure_compare("aaa", "bbbb") } end + def test_fixed_length_secure_compare_uaf + str1 = "A" * 1000000 + evil_obj = Object.new + evil_obj.define_singleton_method(:to_str) do + str1.replace("C" * 1000000) + "B" * 1000000 + end + assert_false(OpenSSL.fixed_length_secure_compare(str1, evil_obj)) + end + def test_secure_compare - refute OpenSSL.secure_compare("aaa", "a") - refute OpenSSL.secure_compare("aaa", "aa") + assert_false(OpenSSL.secure_compare("aaa", "a")) + assert_false(OpenSSL.secure_compare("aaa", "aa")) - assert OpenSSL.secure_compare("aaa", "aaa") + assert_true(OpenSSL.secure_compare("aaa", "aaa")) - refute OpenSSL.secure_compare("aaa", "aaaa") - refute OpenSSL.secure_compare("aaa", "baa") - refute OpenSSL.secure_compare("aaa", "aba") - refute OpenSSL.secure_compare("aaa", "aab") - refute OpenSSL.secure_compare("aaa", "aaab") - refute OpenSSL.secure_compare("aaa", "b") - refute OpenSSL.secure_compare("aaa", "bb") - refute OpenSSL.secure_compare("aaa", "bbb") - refute OpenSSL.secure_compare("aaa", "bbbb") + assert_false(OpenSSL.secure_compare("aaa", "aaaa")) + assert_false(OpenSSL.secure_compare("aaa", "baa")) + assert_false(OpenSSL.secure_compare("aaa", "aba")) + assert_false(OpenSSL.secure_compare("aaa", "aab")) + assert_false(OpenSSL.secure_compare("aaa", "aaab")) + assert_false(OpenSSL.secure_compare("aaa", "b")) + assert_false(OpenSSL.secure_compare("aaa", "bb")) + assert_false(OpenSSL.secure_compare("aaa", "bbb")) + assert_false(OpenSSL.secure_compare("aaa", "bbbb")) end def test_memcmp_timing @@ -63,19 +73,30 @@ class OpenSSL::OSSL < OpenSSL::SSLTestCase end assert_operator(a_b_time, :<, a_c_time * 10, "fixed_length_secure_compare timing test failed") assert_operator(a_c_time, :<, a_b_time * 10, "fixed_length_secure_compare timing test failed") - end + end if ENV["OSSL_TEST_ALL"] == "1" def test_error_data - # X509V3_EXT_nconf_nid() called from OpenSSL::X509::ExtensionFactory#create_ext is a function - # that uses ERR_raise_data() to append additional information about the error. + # X509V3_EXT_nconf_nid() called from + # OpenSSL::X509::ExtensionFactory#create_ext is a function that uses + # ERR_raise_data() to append additional information about the error. # # The generated message should look like: # "subjectAltName = IP:not.a.valid.ip.address: bad ip address (value=not.a.valid.ip.address)" # "subjectAltName = IP:not.a.valid.ip.address: error in extension (name=subjectAltName, value=IP:not.a.valid.ip.address)" + # + # The string inside parentheses is the ERR_TXT_STRING data, and is appended + # by ossl_make_error(), so we check it here. ef = OpenSSL::X509::ExtensionFactory.new - assert_raise_with_message(OpenSSL::X509::ExtensionError, /value=(IP:)?not.a.valid.ip.address\)/) { + e = assert_raise(OpenSSL::X509::ExtensionError) { ef.create_ext("subjectAltName", "IP:not.a.valid.ip.address") } + assert_match(/not.a.valid.ip.address\)\z/, e.message) + + # We currently craft the strings based on ERR_error_string()'s style: + # error:<error code in hex>:<library>:<function>:<reason> (data) + assert_instance_of(Array, e.errors) + assert_match(/\Aerror:.*not.a.valid.ip.address\)\z/, e.errors.last) + assert_include(e.detailed_message, "not.a.valid.ip.address") end end diff --git a/test/openssl/test_pkcs12.rb b/test/openssl/test_pkcs12.rb index 1b5328774e..617c156cbd 100644 --- a/test/openssl/test_pkcs12.rb +++ b/test/openssl/test_pkcs12.rb @@ -3,6 +3,29 @@ require_relative "utils" if defined?(OpenSSL) +# OpenSSL::PKCS12.create calling the PKCS12_create() has the argument mac_iter +# which uses a MAC key using PKCS12KDF which is not FIPS-approved. +# OpenSSL::PKCS12.new with base64-encoded example calling PKCS12_parse() +# verifies the MAC key using PKCS12KDF which is not FIPS-approved. +# +# PBE-SHA1-3DES uses PKCS12KDF which is not FIPS-approved according to the RFC +# 7292 PKCS#12. +# https://datatracker.ietf.org/doc/html/rfc7292#appendix-C +# > The PBES1 encryption scheme defined in PKCS #5 provides a number of +# > algorithm identifiers for deriving keys and IVs; here, we specify a +# > few more, all of which use the procedure detailed in Appendices B.2 +# > and B.3 to construct keys (and IVs, where needed). As is implied by +# > their names, all of the object identifiers below use the hash +# > function SHA-1. +# > ... +# > pbeWithSHAAnd3-KeyTripleDES-CBC OBJECT IDENTIFIER ::= {pkcs-12PbeIds 3} +# +# Note that the pbeWithSHAAnd3-KeyTripleDES-CBC (pkcs12-pbeids 3) in the RFC +# 7292 PKCS#12 means PBE-SHA1-3DES in OpenSSL. PKCS12KDF is used in PKCS#12. +# https://oidref.com/1.2.840.113549.1.12.1.3 +# https://github.com/openssl/openssl/blob/ed57d1e06dca28689190e00d9893e0fd7ecc67c1/crypto/objects/objects.txt#L385 +return if OpenSSL.fips_mode + module OpenSSL class TestPKCS12 < OpenSSL::TestCase DEFAULT_PBE_PKEYS = "PBE-SHA1-3DES" @@ -210,8 +233,13 @@ module OpenSSL end def test_new_with_no_keys - # generated with: - # openssl pkcs12 -certpbe PBE-SHA1-3DES -in <@mycert> -nokeys -export + # Generated with the following steps: + # Print the value of the @mycert such as by `puts @mycert.to_s` and + # save the value as the file `mycert.pem`. + # Run the following commands: + # openssl pkcs12 -certpbe PBE-SHA1-3DES -in <(cat mycert.pem) \ + # -nokeys -export -passout pass:abc123 -out /tmp/p12.out + # base64 -w 60 /tmp/p12.out str = <<~EOF.unpack1("m") MIIGJAIBAzCCBeoGCSqGSIb3DQEHAaCCBdsEggXXMIIF0zCCBc8GCSqGSIb3 DQEHBqCCBcAwggW8AgEAMIIFtQYJKoZIhvcNAQcBMBwGCiqGSIb3DQEMAQMw @@ -259,8 +287,10 @@ AA== end def test_new_with_no_certs - # generated with: - # openssl pkcs12 -inkey fixtures/openssl/pkey/rsa-1.pem -nocerts -export + # Generated with the folowing steps: + # openssl pkcs12 -inkey test/openssl/fixtures/pkey/rsa-1.pem \ + # -nocerts -export -passout pass:abc123 -out /tmp/p12.out + # base64 -w 60 /tmp/p12.out str = <<~EOF.unpack1("m") MIIJ7wIBAzCCCbUGCSqGSIb3DQEHAaCCCaYEggmiMIIJnjCCCZoGCSqGSIb3 DQEHAaCCCYsEggmHMIIJgzCCCX8GCyqGSIb3DQEMCgECoIIJbjCCCWowHAYK diff --git a/test/openssl/test_pkcs7.rb b/test/openssl/test_pkcs7.rb index e8973f73fe..b3129c0cdf 100644 --- a/test/openssl/test_pkcs7.rb +++ b/test/openssl/test_pkcs7.rb @@ -6,95 +6,125 @@ if defined?(OpenSSL) class OpenSSL::TestPKCS7 < OpenSSL::TestCase def setup super - @rsa1024 = Fixtures.pkey("rsa1024") - @rsa2048 = Fixtures.pkey("rsa2048") - ca = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=CA") - ee1 = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=EE1") - ee2 = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=EE2") + @ca_key = Fixtures.pkey("rsa-1") + @ee1_key = Fixtures.pkey("rsa-2") + @ee2_key = Fixtures.pkey("rsa-3") + ca = OpenSSL::X509::Name.new([["CN", "CA"]]) + ee1 = OpenSSL::X509::Name.new([["CN", "EE1"]]) + ee2 = OpenSSL::X509::Name.new([["CN", "EE2"]]) ca_exts = [ - ["basicConstraints","CA:TRUE",true], - ["keyUsage","keyCertSign, cRLSign",true], - ["subjectKeyIdentifier","hash",false], - ["authorityKeyIdentifier","keyid:always",false], + ["basicConstraints", "CA:TRUE", true], + ["keyUsage", "keyCertSign, cRLSign", true], + ["subjectKeyIdentifier", "hash", false], + ["authorityKeyIdentifier", "keyid:always", false], ] - @ca_cert = issue_cert(ca, @rsa2048, 1, ca_exts, nil, nil) + @ca_cert = issue_cert(ca, @ca_key, 1, ca_exts, nil, nil) ee_exts = [ - ["keyUsage","Non Repudiation, Digital Signature, Key Encipherment",true], - ["authorityKeyIdentifier","keyid:always",false], - ["extendedKeyUsage","clientAuth, emailProtection, codeSigning",false], + ["keyUsage", "nonRepudiation, digitalSignature, keyEncipherment", true], + ["authorityKeyIdentifier", "keyid:always", false], + ["extendedKeyUsage", "clientAuth, emailProtection, codeSigning", false], ] - @ee1_cert = issue_cert(ee1, @rsa1024, 2, ee_exts, @ca_cert, @rsa2048) - @ee2_cert = issue_cert(ee2, @rsa1024, 3, ee_exts, @ca_cert, @rsa2048) + @ee1_cert = issue_cert(ee1, @ee1_key, 2, ee_exts, @ca_cert, @ca_key) + @ee2_cert = issue_cert(ee2, @ee2_key, 3, ee_exts, @ca_cert, @ca_key) end def test_signed store = OpenSSL::X509::Store.new store.add_cert(@ca_cert) + + data = "aaaaa\nbbbbb\nccccc\n" ca_certs = [@ca_cert] + tmp = OpenSSL::PKCS7.sign(@ee1_cert, @ee1_key, data, ca_certs) + # TODO: #data contains untranslated content + assert_equal("aaaaa\nbbbbb\nccccc\n", tmp.data) + assert_nil(tmp.error_string) - data = "aaaaa\r\nbbbbb\r\nccccc\r\n" - tmp = OpenSSL::PKCS7.sign(@ee1_cert, @rsa1024, data, ca_certs) p7 = OpenSSL::PKCS7.new(tmp.to_der) + assert_nil(p7.data) + assert_nil(p7.error_string) + + assert_true(p7.verify([], store)) + # AWS-LC does not appear to convert to CRLF automatically + assert_equal("aaaaa\r\nbbbbb\r\nccccc\r\n", p7.data) unless aws_lc? + assert_nil(p7.error_string) + certs = p7.certificates - signers = p7.signers - assert(p7.verify([], store)) - assert_equal(data, p7.data) assert_equal(2, certs.size) - assert_equal(@ee1_cert.subject.to_s, certs[0].subject.to_s) - assert_equal(@ca_cert.subject.to_s, certs[1].subject.to_s) + assert_equal(@ee1_cert.subject, certs[0].subject) + assert_equal(@ca_cert.subject, certs[1].subject) + + signers = p7.signers assert_equal(1, signers.size) assert_equal(@ee1_cert.serial, signers[0].serial) - assert_equal(@ee1_cert.issuer.to_s, signers[0].issuer.to_s) + assert_equal(@ee1_cert.issuer, signers[0].issuer) # AWS-LC does not generate authenticatedAttributes assert_in_delta(Time.now, signers[0].signed_time, 10) unless aws_lc? + assert_false(p7.verify([@ca_cert], OpenSSL::X509::Store.new)) + end + + def test_signed_flags + store = OpenSSL::X509::Store.new + store.add_cert(@ca_cert) + # Normally OpenSSL tries to translate the supplied content into canonical # MIME format (e.g. a newline character is converted into CR+LF). # If the content is a binary, PKCS7::BINARY flag should be used. - + # + # PKCS7::NOATTR flag suppresses authenticatedAttributes. data = "aaaaa\nbbbbb\nccccc\n" flag = OpenSSL::PKCS7::BINARY | OpenSSL::PKCS7::NOATTR - tmp = OpenSSL::PKCS7.sign(@ee1_cert, @rsa1024, data, ca_certs, flag) + tmp = OpenSSL::PKCS7.sign(@ee1_cert, @ee1_key, data, [@ca_cert], flag) p7 = OpenSSL::PKCS7.new(tmp.to_der) - certs = p7.certificates - signers = p7.signers - assert(p7.verify([], store)) + + assert_true(p7.verify([], store)) assert_equal(data, p7.data) + + certs = p7.certificates assert_equal(2, certs.size) - assert_equal(@ee1_cert.subject.to_s, certs[0].subject.to_s) - assert_equal(@ca_cert.subject.to_s, certs[1].subject.to_s) + assert_equal(@ee1_cert.subject, certs[0].subject) + assert_equal(@ca_cert.subject, certs[1].subject) + + signers = p7.signers assert_equal(1, signers.size) assert_equal(@ee1_cert.serial, signers[0].serial) - assert_equal(@ee1_cert.issuer.to_s, signers[0].issuer.to_s) + assert_equal(@ee1_cert.issuer, signers[0].issuer) assert_raise(OpenSSL::PKCS7::PKCS7Error) { signers[0].signed_time } + end + + def test_signed_multiple_signers + store = OpenSSL::X509::Store.new + store.add_cert(@ca_cert) # A signed-data which have multiple signatures can be created # through the following steps. # 1. create two signed-data # 2. copy signerInfo and certificate from one to another - - tmp1 = OpenSSL::PKCS7.sign(@ee1_cert, @rsa1024, data, [], flag) - tmp2 = OpenSSL::PKCS7.sign(@ee2_cert, @rsa1024, data, [], flag) + data = "aaaaa\r\nbbbbb\r\nccccc\r\n" + tmp1 = OpenSSL::PKCS7.sign(@ee1_cert, @ee1_key, data) + tmp2 = OpenSSL::PKCS7.sign(@ee2_cert, @ee2_key, data) tmp1.add_signer(tmp2.signers[0]) tmp1.add_certificate(@ee2_cert) p7 = OpenSSL::PKCS7.new(tmp1.to_der) - certs = p7.certificates - signers = p7.signers - assert(p7.verify([], store)) + assert_true(p7.verify([], store)) assert_equal(data, p7.data) + + certs = p7.certificates assert_equal(2, certs.size) + + signers = p7.signers assert_equal(2, signers.size) assert_equal(@ee1_cert.serial, signers[0].serial) - assert_equal(@ee1_cert.issuer.to_s, signers[0].issuer.to_s) + assert_equal(@ee1_cert.issuer, signers[0].issuer) assert_equal(@ee2_cert.serial, signers[1].serial) - assert_equal(@ee2_cert.issuer.to_s, signers[1].issuer.to_s) + assert_equal(@ee2_cert.issuer, signers[1].issuer) end def test_signed_add_signer data = "aaaaa\nbbbbb\nccccc\n" - psi = OpenSSL::PKCS7::SignerInfo.new(@ee1_cert, @rsa1024, "sha256") + psi = OpenSSL::PKCS7::SignerInfo.new(@ee1_cert, @ee1_key, "sha256") p7 = OpenSSL::PKCS7.new p7.type = :signed p7.add_signer(psi) @@ -113,27 +143,33 @@ class OpenSSL::TestPKCS7 < OpenSSL::TestCase def test_detached_sign store = OpenSSL::X509::Store.new store.add_cert(@ca_cert) - ca_certs = [@ca_cert] data = "aaaaa\nbbbbb\nccccc\n" + ca_certs = [@ca_cert] flag = OpenSSL::PKCS7::BINARY|OpenSSL::PKCS7::DETACHED - tmp = OpenSSL::PKCS7.sign(@ee1_cert, @rsa1024, data, ca_certs, flag) + tmp = OpenSSL::PKCS7.sign(@ee1_cert, @ee1_key, data, ca_certs, flag) p7 = OpenSSL::PKCS7.new(tmp.to_der) - assert_nothing_raised do - OpenSSL::ASN1.decode(p7) - end + assert_predicate(p7, :detached?) + assert_true(p7.detached) - certs = p7.certificates - signers = p7.signers - assert(!p7.verify([], store)) - assert(p7.verify([], store, data)) + assert_false(p7.verify([], store)) + # FIXME: Should it be nil? + assert_equal("", p7.data) + assert_match(/no content|NO_CONTENT/, p7.error_string) + + assert_true(p7.verify([], store, data)) assert_equal(data, p7.data) + assert_nil(p7.error_string) + + certs = p7.certificates assert_equal(2, certs.size) - assert_equal(@ee1_cert.subject.to_s, certs[0].subject.to_s) - assert_equal(@ca_cert.subject.to_s, certs[1].subject.to_s) + assert_equal(@ee1_cert.subject, certs[0].subject) + assert_equal(@ca_cert.subject, certs[1].subject) + + signers = p7.signers assert_equal(1, signers.size) assert_equal(@ee1_cert.serial, signers[0].serial) - assert_equal(@ee1_cert.issuer.to_s, signers[0].issuer.to_s) + assert_equal(@ee1_cert.issuer, signers[0].issuer) end def test_signed_authenticated_attributes @@ -181,6 +217,8 @@ IQCJVpo1FTLZOHSc9UpjS+VKR4cg50Iz0HiPyo6hwjCrwA== end def test_enveloped + omit_on_fips # PKCS #1 v1.5 padding + certs = [@ee1_cert, @ee2_cert] cipher = OpenSSL::Cipher::AES.new("128-CBC") data = "aaaaa\nbbbbb\nccccc\n" @@ -191,15 +229,20 @@ IQCJVpo1FTLZOHSc9UpjS+VKR4cg50Iz0HiPyo6hwjCrwA== assert_equal(:enveloped, p7.type) assert_equal(2, recip.size) - assert_equal(@ca_cert.subject.to_s, recip[0].issuer.to_s) - assert_equal(2, recip[0].serial) - assert_equal(data, p7.decrypt(@rsa1024, @ee1_cert)) + assert_equal(@ca_cert.subject, recip[0].issuer) + assert_equal(@ee1_cert.serial, recip[0].serial) + assert_equal(16, @ee1_key.decrypt(recip[0].enc_key).size) + assert_equal(data, p7.decrypt(@ee1_key, @ee1_cert)) + + assert_equal(@ca_cert.subject, recip[1].issuer) + assert_equal(@ee2_cert.serial, recip[1].serial) + assert_equal(data, p7.decrypt(@ee2_key, @ee2_cert)) - assert_equal(@ca_cert.subject.to_s, recip[1].issuer.to_s) - assert_equal(3, recip[1].serial) - assert_equal(data, p7.decrypt(@rsa1024, @ee2_cert)) + assert_equal(data, p7.decrypt(@ee1_key)) - assert_equal(data, p7.decrypt(@rsa1024)) + assert_raise(OpenSSL::PKCS7::PKCS7Error) { + p7.decrypt(@ca_key, @ca_cert) + } # Default cipher has been removed in v3.3 assert_raise_with_message(ArgumentError, /RC2-40-CBC/) { @@ -207,6 +250,28 @@ IQCJVpo1FTLZOHSc9UpjS+VKR4cg50Iz0HiPyo6hwjCrwA== } end + def test_enveloped_add_recipient + omit_on_fips # PKCS #1 v1.5 padding + + data = "aaaaa\nbbbbb\nccccc\n" + ktri_ee1 = OpenSSL::PKCS7::RecipientInfo.new(@ee1_cert) + ktri_ee2 = OpenSSL::PKCS7::RecipientInfo.new(@ee2_cert) + + tmp = OpenSSL::PKCS7.new + tmp.type = :enveloped + tmp.cipher = "AES-128-CBC" + tmp.add_recipient(ktri_ee1) + tmp.add_recipient(ktri_ee2) + tmp.add_data(data) + + p7 = OpenSSL::PKCS7.new(tmp.to_der) + assert_equal(:enveloped, p7.type) + assert_equal(data, p7.decrypt(@ee1_key, @ee1_cert)) + assert_equal(data, p7.decrypt(@ee2_key, @ee2_cert)) + assert_equal([@ee1_cert.serial, @ee2_cert.serial].sort, + p7.recipients.map(&:serial).sort) + end + def test_data asn1 = OpenSSL::ASN1::Sequence([ OpenSSL::ASN1::ObjectId("pkcs7-data"), @@ -222,6 +287,7 @@ IQCJVpo1FTLZOHSc9UpjS+VKR4cg50Iz0HiPyo6hwjCrwA== p7 = OpenSSL::PKCS7.new(asn1) assert_equal(:data, p7.type) + assert_equal(false, p7.detached) assert_equal(false, p7.detached?) # Not applicable assert_nil(p7.certificates) @@ -232,12 +298,13 @@ IQCJVpo1FTLZOHSc9UpjS+VKR4cg50Iz0HiPyo6hwjCrwA== # PKCS7#verify can't distinguish verification failure and other errors store = OpenSSL::X509::Store.new assert_equal(false, p7.verify([@ee1_cert], store)) - assert_raise(OpenSSL::PKCS7::PKCS7Error) { p7.decrypt(@rsa1024) } + assert_match(/wrong content type|WRONG_CONTENT_TYPE/, p7.error_string) + assert_raise(OpenSSL::PKCS7::PKCS7Error) { p7.decrypt(@ee1_key) } end def test_empty_signed_data_ruby_bug_19974 data = "-----BEGIN PKCS7-----\nMAsGCSqGSIb3DQEHAg==\n-----END PKCS7-----\n" - assert_raise(ArgumentError) { OpenSSL::PKCS7.new(data) } + assert_raise(OpenSSL::PKCS7::PKCS7Error) { OpenSSL::PKCS7.new(data) } data = <<END MIME-Version: 1.0 @@ -252,7 +319,7 @@ END def test_graceful_parsing_failure #[ruby-core:43250] contents = "not a valid PKCS #7 PEM block" - assert_raise(ArgumentError) { OpenSSL::PKCS7.new(contents) } + assert_raise(OpenSSL::PKCS7::PKCS7Error) { OpenSSL::PKCS7.new(contents) } end def test_set_type_signed @@ -273,12 +340,6 @@ END assert_equal(:signedAndEnveloped, p7.type) end - def test_set_type_enveloped - p7 = OpenSSL::PKCS7.new - p7.type = "enveloped" - assert_equal(:enveloped, p7.type) - end - def test_set_type_encrypted p7 = OpenSSL::PKCS7.new p7.type = "encrypted" @@ -293,7 +354,7 @@ END ca_certs = [@ca_cert] data = "aaaaa\r\nbbbbb\r\nccccc\r\n" - tmp = OpenSSL::PKCS7.sign(@ee1_cert, @rsa1024, data, ca_certs) + tmp = OpenSSL::PKCS7.sign(@ee1_cert, @ee1_key, data, ca_certs) p7 = OpenSSL::PKCS7.new(tmp.to_der) smime = OpenSSL::PKCS7.write_smime(p7) assert_equal(true, smime.start_with?(<<END)) @@ -355,7 +416,7 @@ END end def test_decode_ber_constructed_string - pend "AWS-LC ASN.1 parsers has no current support for parsing indefinite BER constructed strings" if aws_lc? + omit_on_fips # PKCS #1 v1.5 padding p7 = OpenSSL::PKCS7.encrypt([@ee1_cert], "content", "aes-128-cbc") @@ -380,8 +441,8 @@ END assert_not_equal(p7.to_der, asn1.to_der) assert_equal(p7.to_der, OpenSSL::PKCS7.new(asn1.to_der).to_der) - assert_equal("content", OpenSSL::PKCS7.new(p7.to_der).decrypt(@rsa1024)) - assert_equal("content", OpenSSL::PKCS7.new(asn1.to_der).decrypt(@rsa1024)) + assert_equal("content", OpenSSL::PKCS7.new(p7.to_der).decrypt(@ee1_key)) + assert_equal("content", OpenSSL::PKCS7.new(asn1.to_der).decrypt(@ee1_key)) end end diff --git a/test/openssl/test_pkey.rb b/test/openssl/test_pkey.rb index 8444cfdcda..93d9e1d42f 100644 --- a/test/openssl/test_pkey.rb +++ b/test/openssl/test_pkey.rb @@ -8,16 +8,7 @@ class OpenSSL::TestPKey < OpenSSL::PKeyTestCase assert_instance_of OpenSSL::PKey::RSA, rsa assert_equal "rsaEncryption", rsa.oid assert_match %r{oid=rsaEncryption}, rsa.inspect - end - - def test_generic_oid_inspect_x25519 - omit_on_fips - - # X25519 private key - x25519 = OpenSSL::PKey.generate_key("X25519") - assert_instance_of OpenSSL::PKey::PKey, x25519 - assert_equal "X25519", x25519.oid - assert_match %r{oid=X25519}, x25519.inspect + assert_match %r{type_name=RSA}, rsa.inspect if openssl?(3, 0, 0) end def test_s_generate_parameters @@ -69,10 +60,115 @@ class OpenSSL::TestPKey < OpenSSL::PKeyTestCase assert_not_equal nil, pkey.private_key end + def test_s_read_pem_unknown_block + # A PEM-encoded certificate and a PEM-encoded private key are combined. + # Check that OSSL_STORE doesn't stop after the first PEM block. + orig = Fixtures.pkey("rsa-1") + subject = OpenSSL::X509::Name.new([["CN", "test"]]) + cert = issue_cert(subject, orig, 1, [], nil, nil) + + input = cert.to_text + cert.to_pem + orig.to_text + orig.private_to_pem + pkey = OpenSSL::PKey.read(input) + assert_equal(orig.private_to_der, pkey.private_to_der) + end + + def test_s_read_der_then_pem + # If the input is valid as both DER and PEM (which allows garbage data + # before and after the block), it is read as DER + # + # TODO: Garbage data after DER should not be allowed, but it is currently + # ignored + orig1 = Fixtures.pkey("rsa-1") + orig2 = Fixtures.pkey("rsa-2") + pkey = OpenSSL::PKey.read(orig1.public_to_der + orig2.private_to_pem) + assert_equal(orig1.public_to_der, pkey.public_to_der) + assert_not_predicate(pkey, :private?) + end + + def test_s_read_passphrase + orig = Fixtures.pkey("rsa-1") + encrypted_pem = orig.private_to_pem("AES-256-CBC", "correct_passphrase") + assert_match(/\A-----BEGIN ENCRYPTED PRIVATE KEY-----/, encrypted_pem) + + # Correct passphrase passed as the second argument + pkey1 = OpenSSL::PKey.read(encrypted_pem, "correct_passphrase") + assert_equal(orig.private_to_der, pkey1.private_to_der) + + # Correct passphrase returned by the block. The block gets false + called = 0 + flag = nil + pkey2 = OpenSSL::PKey.read(encrypted_pem) { |f| + called += 1 + flag = f + "correct_passphrase" + } + assert_equal(orig.private_to_der, pkey2.private_to_der) + assert_equal(1, called) + assert_false(flag) + + # Incorrect passphrase passed. The block is not called + called = 0 + assert_raise(OpenSSL::PKey::PKeyError) { + OpenSSL::PKey.read(encrypted_pem, "incorrect_passphrase") { + called += 1 + } + } + assert_equal(0, called) + + # Incorrect passphrase returned by the block. The block is called only once + called = 0 + assert_raise(OpenSSL::PKey::PKeyError) { + OpenSSL::PKey.read(encrypted_pem) { + called += 1 + "incorrect_passphrase" + } + } + assert_equal(1, called) + end + + def test_s_read_passphrase_tty + omit "https://github.com/aws/aws-lc/pull/2555" if aws_lc? + + orig = Fixtures.pkey("rsa-1") + encrypted_pem = orig.private_to_pem("AES-256-CBC", "correct_passphrase") + + # Correct passphrase passed to OpenSSL's prompt + script = <<~"end;" + require "openssl" + Process.setsid + OpenSSL::PKey.read(#{encrypted_pem.dump}) + puts "ok" + end; + assert_in_out_err([*$:.map { |l| "-I#{l}" }, "-e#{script}"], + "correct_passphrase\n") { |stdout, stderr| + assert_equal(["Enter PEM pass phrase:"], stderr) + assert_equal(["ok"], stdout) + } + + # Incorrect passphrase passed to OpenSSL's prompt + script = <<~"end;" + require "openssl" + Process.setsid + begin + OpenSSL::PKey.read(#{encrypted_pem.dump}) + rescue OpenSSL::PKey::PKeyError + puts "ok" + else + puts "expected OpenSSL::PKey::PKeyError" + end + end; + stdin = "incorrect_passphrase\n" * 5 + assert_in_out_err([*$:.map { |l| "-I#{l}" }, "-e#{script}"], + stdin) { |stdout, stderr| + assert_equal(1, stderr.count("Enter PEM pass phrase:")) + assert_equal(["ok"], stdout) + } + end if ENV["OSSL_TEST_ALL"] == "1" && Process.respond_to?(:setsid) + def test_hmac_sign_verify - pkey = OpenSSL::PKey.generate_key("HMAC", { "key" => "abcd" }) + pkey = OpenSSL::PKey.generate_key("HMAC", { "key" => "a"*32 }) - hmac = OpenSSL::HMAC.new("abcd", "SHA256").update("data").digest + hmac = OpenSSL::HMAC.new("a"*32, "SHA256").update("data").digest assert_equal hmac, pkey.sign("SHA256", "data") # EVP_PKEY_HMAC does not support verify @@ -152,6 +248,8 @@ class OpenSSL::TestPKey < OpenSSL::PKeyTestCase alice = OpenSSL::PKey.read(alice_pem) bob = OpenSSL::PKey.read(bob_pem) assert_instance_of OpenSSL::PKey::PKey, alice + assert_equal "X25519", alice.oid + assert_match %r{oid=X25519}, alice.inspect assert_equal alice_pem, alice.private_to_pem assert_equal bob_pem, bob.public_to_pem assert_equal [shared_secret].pack("H*"), alice.derive(bob) @@ -168,6 +266,25 @@ class OpenSSL::TestPKey < OpenSSL::PKeyTestCase bob.raw_public_key.unpack1("H*") end + def test_ml_dsa + # AWS-LC also supports ML-DSA, but it's implemented in a different way + return unless openssl?(3, 5, 0) + + pkey = OpenSSL::PKey.generate_key("ML-DSA-44") + assert_match(/type_name=ML-DSA-44/, pkey.inspect) + sig = pkey.sign(nil, "data") + assert_equal(2420, sig.bytesize) + assert_equal(true, pkey.verify(nil, sig, "data")) + + pub2 = OpenSSL::PKey.read(pkey.public_to_der) + assert_equal(true, pub2.verify(nil, sig, "data")) + + raw_public_key = pkey.raw_public_key + assert_equal(1312, raw_public_key.bytesize) + pub3 = OpenSSL::PKey.new_raw_public_key("ML-DSA-44", raw_public_key) + assert_equal(true, pub3.verify(nil, sig, "data")) + end + def test_raw_initialize_errors assert_raise(OpenSSL::PKey::PKeyError) { OpenSSL::PKey.new_raw_private_key("foo123", "xxx") } assert_raise(OpenSSL::PKey::PKeyError) { OpenSSL::PKey.new_raw_private_key("ED25519", "xxx") } @@ -176,10 +293,10 @@ class OpenSSL::TestPKey < OpenSSL::PKeyTestCase end def test_compare? - key1 = Fixtures.pkey("rsa1024") - key2 = Fixtures.pkey("rsa1024") - key3 = Fixtures.pkey("rsa2048") - key4 = Fixtures.pkey("dh-1") + key1 = Fixtures.pkey("rsa-1") + key2 = Fixtures.pkey("rsa-1") + key3 = Fixtures.pkey("rsa-2") + key4 = Fixtures.pkey("p256") assert_equal(true, key1.compare?(key2)) assert_equal(true, key1.public_key.compare?(key2)) @@ -194,7 +311,14 @@ class OpenSSL::TestPKey < OpenSSL::PKeyTestCase end def test_to_text - rsa = Fixtures.pkey("rsa1024") + rsa = Fixtures.pkey("rsa-1") assert_include rsa.to_text, "publicExponent" end + + def test_legacy_error_classes + assert_same(OpenSSL::PKey::PKeyError, OpenSSL::PKey::DSAError) + assert_same(OpenSSL::PKey::PKeyError, OpenSSL::PKey::DHError) + assert_same(OpenSSL::PKey::PKeyError, OpenSSL::PKey::ECError) + assert_same(OpenSSL::PKey::PKeyError, OpenSSL::PKey::RSAError) + end end diff --git a/test/openssl/test_pkey_dh.rb b/test/openssl/test_pkey_dh.rb index cf56032cb3..cd13283a2a 100644 --- a/test/openssl/test_pkey_dh.rb +++ b/test/openssl/test_pkey_dh.rb @@ -4,31 +4,42 @@ require_relative 'utils' if defined?(OpenSSL) && defined?(OpenSSL::PKey::DH) class OpenSSL::TestPKeyDH < OpenSSL::PKeyTestCase - NEW_KEYLEN = 2048 - def test_new_empty - dh = OpenSSL::PKey::DH.new - assert_equal nil, dh.p - assert_equal nil, dh.priv_key + # pkeys are immutable with OpenSSL >= 3.0 + if openssl?(3, 0, 0) + assert_raise(ArgumentError) { OpenSSL::PKey::DH.new } + else + dh = OpenSSL::PKey::DH.new + assert_nil(dh.p) + assert_nil(dh.priv_key) + end end def test_new_generate - # This test is slow - dh = OpenSSL::PKey::DH.new(NEW_KEYLEN) - assert_key(dh) - end if ENV["OSSL_TEST_ALL"] + begin + dh1 = OpenSSL::PKey::DH.new(512) + rescue OpenSSL::PKey::PKeyError + omit "generating 512-bit DH parameters failed; " \ + "likely not supported by this OpenSSL build" + end + assert_equal(512, dh1.p.num_bits) + assert_key(dh1) + + dh2 = OpenSSL::PKey::DH.generate(512) + assert_equal(512, dh2.p.num_bits) + assert_key(dh2) + assert_not_equal(dh1.p, dh2.p) + end if ENV["OSSL_TEST_ALL"] == "1" def test_new_break unless openssl? && OpenSSL.fips_mode - assert_nil(OpenSSL::PKey::DH.new(NEW_KEYLEN) { break }) assert_raise(RuntimeError) do - OpenSSL::PKey::DH.new(NEW_KEYLEN) { raise } + OpenSSL::PKey::DH.new(2048) { raise } end else # The block argument is not executed in FIPS case. # See https://github.com/ruby/openssl/issues/692 for details. - assert(OpenSSL::PKey::DH.new(NEW_KEYLEN) { break }) - assert(OpenSSL::PKey::DH.new(NEW_KEYLEN) { raise }) + assert_kind_of(OpenSSL::PKey::DH, OpenSSL::PKey::DH.new(2048) { raise }) end end @@ -51,15 +62,15 @@ class OpenSSL::TestPKeyDH < OpenSSL::PKeyTestCase end def test_DHparams - dh = Fixtures.pkey("dh2048_ffdhe2048") - dh_params = dh.public_key + dh_params = Fixtures.pkey("dh2048_ffdhe2048") asn1 = OpenSSL::ASN1::Sequence([ - OpenSSL::ASN1::Integer(dh.p), - OpenSSL::ASN1::Integer(dh.g) + OpenSSL::ASN1::Integer(dh_params.p), + OpenSSL::ASN1::Integer(dh_params.g) ]) + assert_equal(asn1.to_der, dh_params.to_der) key = OpenSSL::PKey::DH.new(asn1.to_der) - assert_same_dh dh_params, key + assert_same_dh_params(dh_params, key) pem = <<~EOF -----BEGIN DH PARAMETERS----- @@ -71,14 +82,20 @@ class OpenSSL::TestPKeyDH < OpenSSL::PKeyTestCase ssbzSibBsu/6iGtCOGEoXJf//////////wIBAg== -----END DH PARAMETERS----- EOF + assert_equal(pem, dh_params.export) key = OpenSSL::PKey::DH.new(pem) - assert_same_dh dh_params, key + assert_same_dh_params(dh_params, key) + assert_no_key(key) key = OpenSSL::PKey.read(pem) - assert_same_dh dh_params, key - - assert_equal asn1.to_der, dh.to_der - assert_equal pem, dh.export + assert_same_dh_params(dh_params, key) + assert_no_key(key) + + key = OpenSSL::PKey.generate_key(dh_params) + assert_same_dh_params(dh_params, key) + assert_key(key) + assert_equal(dh_params.to_der, key.to_der) + assert_equal(dh_params.to_pem, key.to_pem) end def test_public_key @@ -91,18 +108,20 @@ class OpenSSL::TestPKeyDH < OpenSSL::PKeyTestCase def test_generate_key # Deprecated in v3.0.0; incompatible with OpenSSL 3.0 - # Creates a copy with params only - dh = Fixtures.pkey("dh2048_ffdhe2048").public_key + dh = Fixtures.pkey("dh2048_ffdhe2048") assert_no_key(dh) dh.generate_key! assert_key(dh) - dh2 = dh.public_key + dh2 = OpenSSL::PKey::DH.new(dh.to_der) dh2.generate_key! + assert_not_equal(dh.pub_key, dh2.pub_key) assert_equal(dh.compute_key(dh2.pub_key), dh2.compute_key(dh.pub_key)) end if !openssl?(3, 0, 0) def test_params_ok? + omit_on_fips + # Skip the tests in old OpenSSL version 1.1.1c or early versions before # applying the following commits in OpenSSL 1.1.1d to make `DH_check` # function pass the RFC 7919 FFDHE group texts. @@ -121,7 +140,7 @@ class OpenSSL::TestPKeyDH < OpenSSL::PKeyTestCase # AWS-LC automatically does parameter checks on the parsed params. if aws_lc? - assert_raise(OpenSSL::PKey::DHError) { + assert_raise(OpenSSL::PKey::PKeyError) { OpenSSL::PKey::DH.new(OpenSSL::ASN1::Sequence([ OpenSSL::ASN1::Integer(dh0.p + 1), OpenSSL::ASN1::Integer(dh0.g) @@ -202,14 +221,14 @@ class OpenSSL::TestPKeyDH < OpenSSL::PKeyTestCase end def assert_key(dh) - assert(dh.public?) - assert(dh.private?) - assert(dh.pub_key) - assert(dh.priv_key) + assert_true(dh.public?) + assert_true(dh.private?) + assert_kind_of(OpenSSL::BN, dh.pub_key) + assert_kind_of(OpenSSL::BN, dh.priv_key) end - def assert_same_dh(expected, key) - check_component(expected, key, [:p, :q, :g, :pub_key, :priv_key]) + def assert_same_dh_params(expected, key) + check_component(expected, key, [:p, :q, :g]) end end diff --git a/test/openssl/test_pkey_dsa.rb b/test/openssl/test_pkey_dsa.rb index b882476346..1ec0bf0b4d 100644 --- a/test/openssl/test_pkey_dsa.rb +++ b/test/openssl/test_pkey_dsa.rb @@ -10,7 +10,7 @@ class OpenSSL::TestPKeyDSA < OpenSSL::PKeyTestCase end def test_private - key = Fixtures.pkey("dsa1024") + key = Fixtures.pkey("dsa2048") assert_equal true, key.private? key2 = OpenSSL::PKey::DSA.new(key.to_der) assert_equal true, key2.private? @@ -34,9 +34,14 @@ class OpenSSL::TestPKeyDSA < OpenSSL::PKeyTestCase end def test_new_empty - key = OpenSSL::PKey::DSA.new - assert_nil(key.p) - assert_raise(OpenSSL::PKey::PKeyError) { key.to_der } + # pkeys are immutable with OpenSSL >= 3.0 + if openssl?(3, 0, 0) + assert_raise(ArgumentError) { OpenSSL::PKey::DSA.new } + else + key = OpenSSL::PKey::DSA.new + assert_nil(key.p) + assert_raise(OpenSSL::PKey::PKeyError) { key.to_der } + end end def test_generate @@ -47,11 +52,11 @@ class OpenSSL::TestPKeyDSA < OpenSSL::PKeyTestCase assert_equal 1024, key1024.p.num_bits assert_equal 160, key1024.q.num_bits - key2048 = OpenSSL::PKey::DSA.generate(2048) - assert_equal 2048, key2048.p.num_bits - assert_equal 256, key2048.q.num_bits - if ENV["OSSL_TEST_ALL"] == "1" # slow + key2048 = OpenSSL::PKey::DSA.generate(2048) + assert_equal 2048, key2048.p.num_bits + assert_equal 256, key2048.q.num_bits + key3072 = OpenSSL::PKey::DSA.generate(3072) assert_equal 3072, key3072.p.num_bits assert_equal 256, key3072.q.num_bits @@ -92,7 +97,7 @@ class OpenSSL::TestPKeyDSA < OpenSSL::PKeyTestCase sig = key.syssign(digest) assert_equal true, key.sysverify(digest, sig) assert_equal false, key.sysverify(digest, invalid_sig) - assert_sign_verify_false_or_error{ key.sysverify(digest, malformed_sig) } + assert_sign_verify_false_or_error { key.sysverify(digest, malformed_sig) } assert_equal true, key.verify_raw(nil, sig, digest) assert_equal false, key.verify_raw(nil, invalid_sig, digest) assert_sign_verify_false_or_error { key.verify_raw(nil, malformed_sig, digest) } @@ -109,105 +114,76 @@ class OpenSSL::TestPKeyDSA < OpenSSL::PKeyTestCase def test_DSAPrivateKey # OpenSSL DSAPrivateKey format; similar to RSAPrivateKey - dsa512 = Fixtures.pkey("dsa512") + orig = Fixtures.pkey("dsa2048") asn1 = OpenSSL::ASN1::Sequence([ OpenSSL::ASN1::Integer(0), - OpenSSL::ASN1::Integer(dsa512.p), - OpenSSL::ASN1::Integer(dsa512.q), - OpenSSL::ASN1::Integer(dsa512.g), - OpenSSL::ASN1::Integer(dsa512.pub_key), - OpenSSL::ASN1::Integer(dsa512.priv_key) + OpenSSL::ASN1::Integer(orig.p), + OpenSSL::ASN1::Integer(orig.q), + OpenSSL::ASN1::Integer(orig.g), + OpenSSL::ASN1::Integer(orig.pub_key), + OpenSSL::ASN1::Integer(orig.priv_key) ]) key = OpenSSL::PKey::DSA.new(asn1.to_der) assert_predicate key, :private? - assert_same_dsa dsa512, key - - pem = <<~EOF - -----BEGIN DSA PRIVATE KEY----- - MIH4AgEAAkEA5lB4GvEwjrsMlGDqGsxrbqeFRh6o9OWt6FgTYiEEHaOYhkIxv0Ok - RZPDNwOG997mDjBnvDJ1i56OmS3MbTnovwIVAJgub/aDrSDB4DZGH7UyarcaGy6D - AkB9HdFw/3td8K4l1FZHv7TCZeJ3ZLb7dF3TWoGUP003RCqoji3/lHdKoVdTQNuR - S/m6DlCwhjRjiQ/lBRgCLCcaAkEAjN891JBjzpMj4bWgsACmMggFf57DS0Ti+5++ - Q1VB8qkJN7rA7/2HrCR3gTsWNb1YhAsnFsoeRscC+LxXoXi9OAIUBG98h4tilg6S - 55jreJD3Se3slps= - -----END DSA PRIVATE KEY----- - EOF + assert_same_dsa orig, key + + pem = der_to_pem(asn1.to_der, "DSA PRIVATE KEY") key = OpenSSL::PKey::DSA.new(pem) - assert_same_dsa dsa512, key + assert_same_dsa orig, key - assert_equal asn1.to_der, dsa512.to_der - assert_equal pem, dsa512.export + assert_equal asn1.to_der, orig.to_der + assert_equal pem, orig.export end def test_DSAPrivateKey_encrypted - # key = abcdef - dsa512 = Fixtures.pkey("dsa512") - pem = <<~EOF - -----BEGIN DSA PRIVATE KEY----- - Proc-Type: 4,ENCRYPTED - DEK-Info: AES-128-CBC,F8BB7BFC7EAB9118AC2E3DA16C8DB1D9 - - D2sIzsM9MLXBtlF4RW42u2GB9gX3HQ3prtVIjWPLaKBYoToRUiv8WKsjptfZuLSB - 74ZPdMS7VITM+W1HIxo/tjS80348Cwc9ou8H/E6WGat8ZUk/igLOUEII+coQS6qw - QpuLMcCIavevX0gjdjEIkojBB81TYDofA1Bp1z1zDI/2Zhw822xapI79ZF7Rmywt - OSyWzFaGipgDpdFsGzvT6//z0jMr0AuJVcZ0VJ5lyPGQZAeVBlbYEI4T72cC5Cz7 - XvLiaUtum6/sASD2PQqdDNpgx/WA6Vs1Po2kIUQIM5TIwyJI0GdykZcYm6xIK/ta - Wgx6c8K+qBAIVrilw3EWxw== - -----END DSA PRIVATE KEY----- - EOF + # OpenSSL DSAPrivateKey with OpenSSL encryption + orig = Fixtures.pkey("dsa2048") + + pem = der_to_encrypted_pem(orig.to_der, "DSA PRIVATE KEY", "abcdef") key = OpenSSL::PKey::DSA.new(pem, "abcdef") - assert_same_dsa dsa512, key + assert_same_dsa orig, key key = OpenSSL::PKey::DSA.new(pem) { "abcdef" } - assert_same_dsa dsa512, key + assert_same_dsa orig, key cipher = OpenSSL::Cipher.new("aes-128-cbc") - exported = dsa512.to_pem(cipher, "abcdef\0\1") - assert_same_dsa dsa512, OpenSSL::PKey::DSA.new(exported, "abcdef\0\1") - assert_raise(OpenSSL::PKey::DSAError) { + exported = orig.to_pem(cipher, "abcdef\0\1") + assert_same_dsa orig, OpenSSL::PKey::DSA.new(exported, "abcdef\0\1") + assert_raise(OpenSSL::PKey::PKeyError) { OpenSSL::PKey::DSA.new(exported, "abcdef") } end def test_PUBKEY - dsa512 = Fixtures.pkey("dsa512") - dsa512pub = OpenSSL::PKey::DSA.new(dsa512.public_to_der) + orig = Fixtures.pkey("dsa2048") + pub = OpenSSL::PKey::DSA.new(orig.public_to_der) asn1 = OpenSSL::ASN1::Sequence([ OpenSSL::ASN1::Sequence([ OpenSSL::ASN1::ObjectId("DSA"), OpenSSL::ASN1::Sequence([ - OpenSSL::ASN1::Integer(dsa512.p), - OpenSSL::ASN1::Integer(dsa512.q), - OpenSSL::ASN1::Integer(dsa512.g) + OpenSSL::ASN1::Integer(orig.p), + OpenSSL::ASN1::Integer(orig.q), + OpenSSL::ASN1::Integer(orig.g) ]) ]), OpenSSL::ASN1::BitString( - OpenSSL::ASN1::Integer(dsa512.pub_key).to_der + OpenSSL::ASN1::Integer(orig.pub_key).to_der ) ]) key = OpenSSL::PKey::DSA.new(asn1.to_der) assert_not_predicate key, :private? - assert_same_dsa dsa512pub, key - - pem = <<~EOF - -----BEGIN PUBLIC KEY----- - MIHxMIGoBgcqhkjOOAQBMIGcAkEA5lB4GvEwjrsMlGDqGsxrbqeFRh6o9OWt6FgT - YiEEHaOYhkIxv0OkRZPDNwOG997mDjBnvDJ1i56OmS3MbTnovwIVAJgub/aDrSDB - 4DZGH7UyarcaGy6DAkB9HdFw/3td8K4l1FZHv7TCZeJ3ZLb7dF3TWoGUP003RCqo - ji3/lHdKoVdTQNuRS/m6DlCwhjRjiQ/lBRgCLCcaA0QAAkEAjN891JBjzpMj4bWg - sACmMggFf57DS0Ti+5++Q1VB8qkJN7rA7/2HrCR3gTsWNb1YhAsnFsoeRscC+LxX - oXi9OA== - -----END PUBLIC KEY----- - EOF + assert_same_dsa pub, key + + pem = der_to_pem(asn1.to_der, "PUBLIC KEY") key = OpenSSL::PKey::DSA.new(pem) - assert_same_dsa dsa512pub, key + assert_same_dsa pub, key assert_equal asn1.to_der, key.to_der assert_equal pem, key.export - assert_equal asn1.to_der, dsa512.public_to_der + assert_equal asn1.to_der, orig.public_to_der assert_equal asn1.to_der, key.public_to_der - assert_equal pem, dsa512.public_to_pem + assert_equal pem, orig.public_to_pem assert_equal pem, key.public_to_pem end @@ -258,7 +234,7 @@ fWLOqqkzFeRrYMDzUpl36XktY6Yq8EJYlW9pCMmBVNy/dQ== end def test_dup - key = Fixtures.pkey("dsa1024") + key = Fixtures.pkey("dsa2048") key2 = key.dup assert_equal key.params, key2.params @@ -270,7 +246,7 @@ fWLOqqkzFeRrYMDzUpl36XktY6Yq8EJYlW9pCMmBVNy/dQ== end def test_marshal - key = Fixtures.pkey("dsa1024") + key = Fixtures.pkey("dsa2048") deserialized = Marshal.load(Marshal.dump(key)) assert_equal key.to_der, deserialized.to_der diff --git a/test/openssl/test_pkey_ec.rb b/test/openssl/test_pkey_ec.rb index 1953b4c2da..ec97a747a3 100644 --- a/test/openssl/test_pkey_ec.rb +++ b/test/openssl/test_pkey_ec.rb @@ -4,19 +4,9 @@ require_relative 'utils' if defined?(OpenSSL) class OpenSSL::TestEC < OpenSSL::PKeyTestCase - def test_ec_key + def test_ec_key_new key1 = OpenSSL::PKey::EC.generate("prime256v1") - # PKey is immutable in OpenSSL >= 3.0; constructing an empty EC object is - # deprecated - if !openssl?(3, 0, 0) - key2 = OpenSSL::PKey::EC.new - key2.group = key1.group - key2.private_key = key1.private_key - key2.public_key = key1.public_key - assert_equal key1.to_der, key2.to_der - end - key3 = OpenSSL::PKey::EC.new(key1) assert_equal key1.to_der, key3.to_der @@ -35,6 +25,23 @@ class OpenSSL::TestEC < OpenSSL::PKeyTestCase end end + def test_ec_key_new_empty + # pkeys are immutable with OpenSSL >= 3.0; constructing an empty EC object is + # disallowed + if openssl?(3, 0, 0) + assert_raise(ArgumentError) { OpenSSL::PKey::EC.new } + else + key = OpenSSL::PKey::EC.new + assert_nil(key.group) + + p256 = Fixtures.pkey("p256") + key.group = p256.group + key.private_key = p256.private_key + key.public_key = p256.public_key + assert_equal(p256.to_der, key.to_der) + end + end + def test_builtin_curves builtin_curves = OpenSSL::PKey::EC.builtin_curves assert_not_empty builtin_curves @@ -47,7 +54,9 @@ class OpenSSL::TestEC < OpenSSL::PKeyTestCase end def test_generate - assert_raise(OpenSSL::PKey::ECError) { OpenSSL::PKey::EC.generate("non-existent") } + assert_raise(OpenSSL::PKey::PKeyError) { + OpenSSL::PKey::EC.generate("non-existent") + } g = OpenSSL::PKey::EC::Group.new("prime256v1") ec = OpenSSL::PKey::EC.generate(g) assert_equal(true, ec.private?) @@ -58,7 +67,7 @@ class OpenSSL::TestEC < OpenSSL::PKeyTestCase def test_generate_key ec = OpenSSL::PKey::EC.new("prime256v1") assert_equal false, ec.private? - assert_raise(OpenSSL::PKey::ECError) { ec.to_der } + assert_raise(OpenSSL::PKey::PKeyError) { ec.to_der } ec.generate_key! assert_equal true, ec.private? assert_nothing_raised { ec.to_der } @@ -72,6 +81,8 @@ class OpenSSL::TestEC < OpenSSL::PKeyTestCase end def test_check_key + omit_on_fips + key0 = Fixtures.pkey("p256") assert_equal(true, key0.check_key) assert_equal(true, key0.private?) @@ -100,13 +111,13 @@ class OpenSSL::TestEC < OpenSSL::PKeyTestCase assert_raise(OpenSSL::PKey::PKeyError) { OpenSSL::PKey.read(ec_key_data) } else key4 = OpenSSL::PKey.read(ec_key_data) - assert_raise(OpenSSL::PKey::ECError) { key4.check_key } + assert_raise(OpenSSL::PKey::PKeyError) { key4.check_key } end # EC#private_key= is deprecated in 3.0 and won't work on OpenSSL 3.0 if !openssl?(3, 0, 0) key2.private_key += 1 - assert_raise(OpenSSL::PKey::ECError) { key2.check_key } + assert_raise(OpenSSL::PKey::PKeyError) { key2.check_key } end end @@ -260,7 +271,7 @@ class OpenSSL::TestEC < OpenSSL::PKeyTestCase cipher = OpenSSL::Cipher.new("aes-128-cbc") exported = p256.to_pem(cipher, "abcdef\0\1") assert_same_ec p256, OpenSSL::PKey::EC.new(exported, "abcdef\0\1") - assert_raise(OpenSSL::PKey::ECError) { + assert_raise(OpenSSL::PKey::PKeyError) { OpenSSL::PKey::EC.new(exported, "abcdef") } end @@ -334,6 +345,15 @@ class OpenSSL::TestEC < OpenSSL::PKeyTestCase assert_equal group1.degree, group4.degree end + def test_ec_group_initialize_error_message + # Test that passing 2 arguments raises the helpful error + e = assert_raise(ArgumentError) do + OpenSSL::PKey::EC::Group.new(:GFp, 123) + end + + assert_equal("wrong number of arguments (given 2, expected 1 or 4)", e.message) + end + def test_ec_point group = OpenSSL::PKey::EC::Group.new("prime256v1") key = OpenSSL::PKey::EC.generate(group) @@ -358,18 +378,26 @@ class OpenSSL::TestEC < OpenSSL::PKeyTestCase point2.to_octet_string(:uncompressed) assert_equal point2.to_octet_string(:uncompressed), point3.to_octet_string(:uncompressed) + end + def test_small_curve begin group = OpenSSL::PKey::EC::Group.new(:GFp, 17, 2, 2) group.point_conversion_form = :uncompressed generator = OpenSSL::PKey::EC::Point.new(group, B(%w{ 04 05 01 })) group.set_generator(generator, 19, 1) - point = OpenSSL::PKey::EC::Point.new(group, B(%w{ 04 06 03 })) rescue OpenSSL::PKey::EC::Group::Error pend "Patched OpenSSL rejected curve" if /unsupported field/ =~ $!.message raise end - + assert_equal 17.to_bn.num_bits, group.degree + assert_equal B(%w{ 04 05 01 }), + group.generator.to_octet_string(:uncompressed) + assert_equal 19.to_bn, group.order + assert_equal 1.to_bn, group.cofactor + assert_nil group.curve_name + + point = OpenSSL::PKey::EC::Point.new(group, B(%w{ 04 06 03 })) assert_equal 0x040603.to_bn, point.to_bn assert_equal 0x040603.to_bn, point.to_bn(:uncompressed) assert_equal 0x0306.to_bn, point.to_bn(:compressed) diff --git a/test/openssl/test_pkey_rsa.rb b/test/openssl/test_pkey_rsa.rb index 850c16a029..1716aef380 100644 --- a/test/openssl/test_pkey_rsa.rb +++ b/test/openssl/test_pkey_rsa.rb @@ -6,40 +6,38 @@ if defined?(OpenSSL) class OpenSSL::TestPKeyRSA < OpenSSL::PKeyTestCase def test_no_private_exp key = OpenSSL::PKey::RSA.new - rsa = Fixtures.pkey("rsa2048") + rsa = Fixtures.pkey("rsa-1") key.set_key(rsa.n, rsa.e, nil) key.set_factors(rsa.p, rsa.q) - assert_raise(OpenSSL::PKey::RSAError){ key.private_encrypt("foo") } - assert_raise(OpenSSL::PKey::RSAError){ key.private_decrypt("foo") } + assert_raise(OpenSSL::PKey::PKeyError){ key.private_encrypt("foo") } + assert_raise(OpenSSL::PKey::PKeyError){ key.private_decrypt("foo") } end if !openssl?(3, 0, 0) # Impossible state in OpenSSL 3.0 def test_private - key = Fixtures.pkey("rsa2048") + key = Fixtures.pkey("rsa-1") # Generated by DER key2 = OpenSSL::PKey::RSA.new(key.to_der) - assert(key2.private?) + assert_true(key2.private?) # public key key3 = key.public_key - assert(!key3.private?) + assert_false(key3.private?) # Generated by public key DER key4 = OpenSSL::PKey::RSA.new(key3.to_der) - assert(!key4.private?) - rsa1024 = Fixtures.pkey("rsa1024") + assert_false(key4.private?) if !openssl?(3, 0, 0) - key = OpenSSL::PKey::RSA.new # Generated by RSA#set_key key5 = OpenSSL::PKey::RSA.new - key5.set_key(rsa1024.n, rsa1024.e, rsa1024.d) - assert(key5.private?) + key5.set_key(key.n, key.e, key.d) + assert_true(key5.private?) # Generated by RSA#set_key, without d key6 = OpenSSL::PKey::RSA.new - key6.set_key(rsa1024.n, rsa1024.e, nil) - assert(!key6.private?) + key6.set_key(key.n, key.e, nil) + assert_false(key6.private?) end end @@ -61,6 +59,16 @@ class OpenSSL::TestPKeyRSA < OpenSSL::PKeyTestCase assert_equal 3, key.e end + def test_new_empty + # pkeys are immutable with OpenSSL >= 3.0 + if openssl?(3, 0, 0) + assert_raise(ArgumentError) { OpenSSL::PKey::RSA.new } + else + key = OpenSSL::PKey::RSA.new + assert_nil(key.n) + end + end + def test_s_generate key1 = OpenSSL::PKey::RSA.generate(2048) assert_equal 2048, key1.n.num_bits @@ -172,7 +180,7 @@ class OpenSSL::TestPKeyRSA < OpenSSL::PKeyTestCase # Failure cases assert_raise(ArgumentError){ key.private_encrypt() } assert_raise(ArgumentError){ key.private_encrypt("hi", 1, nil) } - assert_raise(OpenSSL::PKey::RSAError){ key.private_encrypt(plain0, 666) } + assert_raise(OpenSSL::PKey::PKeyError){ key.private_encrypt(plain0, 666) } end @@ -181,7 +189,7 @@ class OpenSSL::TestPKeyRSA < OpenSSL::PKeyTestCase assert_raise(OpenSSL::PKey::PKeyError, "[Bug #12783]") { rsa.verify("SHA1", "a", "b") } - end + end unless openssl?(3, 0, 0) # Empty RSA is not possible with OpenSSL >= 3.0 def test_sign_verify_pss key = Fixtures.pkey("rsa2048") @@ -223,7 +231,7 @@ class OpenSSL::TestPKeyRSA < OpenSSL::PKeyTestCase key.verify_pss("SHA256", signature, data, salt_length: :auto, mgf1_hash: "SHA256") end - assert_raise(OpenSSL::PKey::RSAError) { + assert_raise(OpenSSL::PKey::PKeyError) { key.sign_pss("SHA256", data, salt_length: 223, mgf1_hash: "SHA256") } end @@ -270,57 +278,57 @@ class OpenSSL::TestPKeyRSA < OpenSSL::PKeyTestCase end def test_export - rsa1024 = Fixtures.pkey("rsa1024") + orig = Fixtures.pkey("rsa-1") - pub = OpenSSL::PKey.read(rsa1024.public_to_der) - assert_not_equal rsa1024.export, pub.export - assert_equal rsa1024.public_to_pem, pub.export + pub = OpenSSL::PKey.read(orig.public_to_der) + assert_not_equal orig.export, pub.export + assert_equal orig.public_to_pem, pub.export # PKey is immutable in OpenSSL >= 3.0 if !openssl?(3, 0, 0) key = OpenSSL::PKey::RSA.new # key has only n, e and d - key.set_key(rsa1024.n, rsa1024.e, rsa1024.d) - assert_equal rsa1024.public_key.export, key.export + key.set_key(orig.n, orig.e, orig.d) + assert_equal orig.public_key.export, key.export # key has only n, e, d, p and q - key.set_factors(rsa1024.p, rsa1024.q) - assert_equal rsa1024.public_key.export, key.export + key.set_factors(orig.p, orig.q) + assert_equal orig.public_key.export, key.export # key has n, e, d, p, q, dmp1, dmq1 and iqmp - key.set_crt_params(rsa1024.dmp1, rsa1024.dmq1, rsa1024.iqmp) - assert_equal rsa1024.export, key.export + key.set_crt_params(orig.dmp1, orig.dmq1, orig.iqmp) + assert_equal orig.export, key.export end end def test_to_der - rsa1024 = Fixtures.pkey("rsa1024") + orig = Fixtures.pkey("rsa-1") - pub = OpenSSL::PKey.read(rsa1024.public_to_der) - assert_not_equal rsa1024.to_der, pub.to_der - assert_equal rsa1024.public_to_der, pub.to_der + pub = OpenSSL::PKey.read(orig.public_to_der) + assert_not_equal orig.to_der, pub.to_der + assert_equal orig.public_to_der, pub.to_der # PKey is immutable in OpenSSL >= 3.0 if !openssl?(3, 0, 0) key = OpenSSL::PKey::RSA.new # key has only n, e and d - key.set_key(rsa1024.n, rsa1024.e, rsa1024.d) - assert_equal rsa1024.public_key.to_der, key.to_der + key.set_key(orig.n, orig.e, orig.d) + assert_equal orig.public_key.to_der, key.to_der # key has only n, e, d, p and q - key.set_factors(rsa1024.p, rsa1024.q) - assert_equal rsa1024.public_key.to_der, key.to_der + key.set_factors(orig.p, orig.q) + assert_equal orig.public_key.to_der, key.to_der # key has n, e, d, p, q, dmp1, dmq1 and iqmp - key.set_crt_params(rsa1024.dmp1, rsa1024.dmq1, rsa1024.iqmp) - assert_equal rsa1024.to_der, key.to_der + key.set_crt_params(orig.dmp1, orig.dmq1, orig.iqmp) + assert_equal orig.to_der, key.to_der end end def test_RSAPrivateKey - rsa = Fixtures.pkey("rsa2048") + rsa = Fixtures.pkey("rsa-1") asn1 = OpenSSL::ASN1::Sequence([ OpenSSL::ASN1::Integer(0), OpenSSL::ASN1::Integer(rsa.n), @@ -336,35 +344,7 @@ class OpenSSL::TestPKeyRSA < OpenSSL::PKeyTestCase assert_predicate key, :private? assert_same_rsa rsa, key - pem = <<~EOF - -----BEGIN RSA PRIVATE KEY----- - MIIEpAIBAAKCAQEAuV9ht9J7k4NBs38jOXvvTKY9gW8nLICSno5EETR1cuF7i4pN - s9I1QJGAFAX0BEO4KbzXmuOvfCpD3CU+Slp1enenfzq/t/e/1IRW0wkJUJUFQign - 4CtrkJL+P07yx18UjyPlBXb81ApEmAB5mrJVSrWmqbjs07JbuS4QQGGXLc+Su96D - kYKmSNVjBiLxVVSpyZfAY3hD37d60uG+X8xdW5v68JkRFIhdGlb6JL8fllf/A/bl - NwdJOhVr9mESHhwGjwfSeTDPfd8ZLE027E5lyAVX9KZYcU00mOX+fdxOSnGqS/8J - DRh0EPHDL15RcJjV2J6vZjPb0rOYGDoMcH+94wIDAQABAoIBAAzsamqfYQAqwXTb - I0CJtGg6msUgU7HVkOM+9d3hM2L791oGHV6xBAdpXW2H8LgvZHJ8eOeSghR8+dgq - PIqAffo4x1Oma+FOg3A0fb0evyiACyrOk+EcBdbBeLo/LcvahBtqnDfiUMQTpy6V - seSoFCwuN91TSCeGIsDpRjbG1vxZgtx+uI+oH5+ytqJOmfCksRDCkMglGkzyfcl0 - Xc5CUhIJ0my53xijEUQl19rtWdMnNnnkdbG8PT3LZlOta5Do86BElzUYka0C6dUc - VsBDQ0Nup0P6rEQgy7tephHoRlUGTYamsajGJaAo1F3IQVIrRSuagi7+YpSpCqsW - wORqorkCgYEA7RdX6MDVrbw7LePnhyuaqTiMK+055/R1TqhB1JvvxJ1CXk2rDL6G - 0TLHQ7oGofd5LYiemg4ZVtWdJe43BPZlVgT6lvL/iGo8JnrncB9Da6L7nrq/+Rvj - XGjf1qODCK+LmreZWEsaLPURIoR/Ewwxb9J2zd0CaMjeTwafJo1CZvcCgYEAyCgb - aqoWvUecX8VvARfuA593Lsi50t4MEArnOXXcd1RnXoZWhbx5rgO8/ATKfXr0BK/n - h2GF9PfKzHFm/4V6e82OL7gu/kLy2u9bXN74vOvWFL5NOrOKPM7Kg+9I131kNYOw - Ivnr/VtHE5s0dY7JChYWE1F3vArrOw3T00a4CXUCgYEA0SqY+dS2LvIzW4cHCe9k - IQqsT0yYm5TFsUEr4sA3xcPfe4cV8sZb9k/QEGYb1+SWWZ+AHPV3UW5fl8kTbSNb - v4ng8i8rVVQ0ANbJO9e5CUrepein2MPL0AkOATR8M7t7dGGpvYV0cFk8ZrFx0oId - U0PgYDotF/iueBWlbsOM430CgYEAqYI95dFyPI5/AiSkY5queeb8+mQH62sdcCCr - vd/w/CZA/K5sbAo4SoTj8dLk4evU6HtIa0DOP63y071eaxvRpTNqLUOgmLh+D6gS - Cc7TfLuFrD+WDBatBd5jZ+SoHccVrLR/4L8jeodo5FPW05A+9gnKXEXsTxY4LOUC - 9bS4e1kCgYAqVXZh63JsMwoaxCYmQ66eJojKa47VNrOeIZDZvd2BPVf30glBOT41 - gBoDG3WMPZoQj9pb7uMcrnvs4APj2FIhMU8U15LcPAj59cD6S6rWnAxO8NFK7HQG - 4Jxg3JNNf8ErQoCHb1B3oVdXJkmbJkARoDpBKmTCgKtP8ADYLmVPQw== - -----END RSA PRIVATE KEY----- - EOF + pem = der_to_pem(asn1.to_der, "RSA PRIVATE KEY") key = OpenSSL::PKey::RSA.new(pem) assert_same_rsa rsa, key @@ -379,69 +359,46 @@ class OpenSSL::TestPKeyRSA < OpenSSL::PKeyTestCase end def test_RSAPrivateKey_encrypted + # PKCS #1 RSAPrivateKey with OpenSSL encryption omit_on_fips - rsa1024 = Fixtures.pkey("rsa1024") - # key = abcdef - pem = <<~EOF - -----BEGIN RSA PRIVATE KEY----- - Proc-Type: 4,ENCRYPTED - DEK-Info: AES-128-CBC,733F5302505B34701FC41F5C0746E4C0 - - zgJniZZQfvv8TFx3LzV6zhAQVayvQVZlAYqFq2yWbbxzF7C+IBhKQle9IhUQ9j/y - /jkvol550LS8vZ7TX5WxyDLe12cdqzEvpR6jf3NbxiNysOCxwG4ErhaZGP+krcoB - ObuL0nvls/+3myy5reKEyy22+0GvTDjaChfr+FwJjXMG+IBCLscYdgZC1LQL6oAn - 9xY5DH3W7BW4wR5ttxvtN32TkfVQh8xi3jrLrduUh+hV8DTiAiLIhv0Vykwhep2p - WZA+7qbrYaYM8GLLgLrb6LfBoxeNxAEKiTpl1quFkm+Hk1dKq0EhVnxHf92x0zVF - jRGZxAMNcrlCoE4f5XK45epVZSZvihdo1k73GPbp84aZ5P/xlO4OwZ3i4uCQXynl - jE9c+I+4rRWKyPz9gkkqo0+teJL8ifeKt/3ab6FcdA0aArynqmsKJMktxmNu83We - YVGEHZPeOlyOQqPvZqWsLnXQUfg54OkbuV4/4mWSIzxFXdFy/AekSeJugpswMXqn - oNck4qySNyfnlyelppXyWWwDfVus9CVAGZmJQaJExHMT/rQFRVchlmY0Ddr5O264 - gcjv90o1NBOc2fNcqjivuoX7ROqys4K/YdNQ1HhQ7usJghADNOtuLI8ZqMh9akXD - Eqp6Ne97wq1NiJj0nt3SJlzTnOyTjzrTe0Y+atPkVKp7SsjkATMI9JdhXwGhWd7a - qFVl0owZiDasgEhyG2K5L6r+yaJLYkPVXZYC/wtWC3NEchnDWZGQcXzB4xROCQkD - OlWNYDkPiZioeFkA3/fTMvG4moB2Pp9Q4GU5fJ6k43Ccu1up8dX/LumZb4ecg5/x - -----END RSA PRIVATE KEY----- - EOF + rsa = Fixtures.pkey("rsa2048") + + pem = der_to_encrypted_pem(rsa.to_der, "RSA PRIVATE KEY", "abcdef") key = OpenSSL::PKey::RSA.new(pem, "abcdef") - assert_same_rsa rsa1024, key + assert_same_rsa rsa, key key = OpenSSL::PKey::RSA.new(pem) { "abcdef" } - assert_same_rsa rsa1024, key + assert_same_rsa rsa, key cipher = OpenSSL::Cipher.new("aes-128-cbc") - exported = rsa1024.to_pem(cipher, "abcdef\0\1") - assert_same_rsa rsa1024, OpenSSL::PKey::RSA.new(exported, "abcdef\0\1") - assert_raise(OpenSSL::PKey::RSAError) { + exported = rsa.to_pem(cipher, "abcdef\0\1") + assert_same_rsa rsa, OpenSSL::PKey::RSA.new(exported, "abcdef\0\1") + assert_raise(OpenSSL::PKey::PKeyError) { OpenSSL::PKey::RSA.new(exported, "abcdef") } end def test_RSAPublicKey - rsa1024 = Fixtures.pkey("rsa1024") - rsa1024pub = OpenSSL::PKey::RSA.new(rsa1024.public_to_der) + # PKCS #1 RSAPublicKey. Only decoding is supported + orig = Fixtures.pkey("rsa-1") + pub = OpenSSL::PKey::RSA.new(orig.public_to_der) asn1 = OpenSSL::ASN1::Sequence([ - OpenSSL::ASN1::Integer(rsa1024.n), - OpenSSL::ASN1::Integer(rsa1024.e) + OpenSSL::ASN1::Integer(orig.n), + OpenSSL::ASN1::Integer(orig.e) ]) key = OpenSSL::PKey::RSA.new(asn1.to_der) assert_not_predicate key, :private? - assert_same_rsa rsa1024pub, key + assert_same_rsa pub, key - pem = <<~EOF - -----BEGIN RSA PUBLIC KEY----- - MIGJAoGBAMvCxLDUQKc+1P4+Q6AeFwYDvWfALb+cvzlUEadGoPE6qNWHsLFoo8RF - geyTgE8KQTduu1OE9Zz2SMcRBDu5/1jWtsLPSVrI2ofLLBARUsWanVyki39DeB4u - /xkP2mKGjAokPIwOI3oCthSZlzO9bj3voxTf6XngTqUX8l8URTmHAgMBAAE= - -----END RSA PUBLIC KEY----- - EOF + pem = der_to_pem(asn1.to_der, "RSA PUBLIC KEY") key = OpenSSL::PKey::RSA.new(pem) - assert_same_rsa rsa1024pub, key + assert_same_rsa pub, key end def test_PUBKEY - rsa1024 = Fixtures.pkey("rsa1024") - rsa1024pub = OpenSSL::PKey::RSA.new(rsa1024.public_to_der) + orig = Fixtures.pkey("rsa-1") + pub = OpenSSL::PKey::RSA.new(orig.public_to_der) asn1 = OpenSSL::ASN1::Sequence([ OpenSSL::ASN1::Sequence([ @@ -450,39 +407,32 @@ class OpenSSL::TestPKeyRSA < OpenSSL::PKeyTestCase ]), OpenSSL::ASN1::BitString( OpenSSL::ASN1::Sequence([ - OpenSSL::ASN1::Integer(rsa1024.n), - OpenSSL::ASN1::Integer(rsa1024.e) + OpenSSL::ASN1::Integer(orig.n), + OpenSSL::ASN1::Integer(orig.e) ]).to_der ) ]) key = OpenSSL::PKey::RSA.new(asn1.to_der) assert_not_predicate key, :private? - assert_same_rsa rsa1024pub, key + assert_same_rsa pub, key - pem = <<~EOF - -----BEGIN PUBLIC KEY----- - MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDLwsSw1ECnPtT+PkOgHhcGA71n - wC2/nL85VBGnRqDxOqjVh7CxaKPERYHsk4BPCkE3brtThPWc9kjHEQQ7uf9Y1rbC - z0layNqHyywQEVLFmp1cpIt/Q3geLv8ZD9pihowKJDyMDiN6ArYUmZczvW4976MU - 3+l54E6lF/JfFEU5hwIDAQAB - -----END PUBLIC KEY----- - EOF + pem = der_to_pem(asn1.to_der, "PUBLIC KEY") key = OpenSSL::PKey::RSA.new(pem) - assert_same_rsa rsa1024pub, key + assert_same_rsa pub, key assert_equal asn1.to_der, key.to_der assert_equal pem, key.export - assert_equal asn1.to_der, rsa1024.public_to_der + assert_equal asn1.to_der, orig.public_to_der assert_equal asn1.to_der, key.public_to_der - assert_equal pem, rsa1024.public_to_pem + assert_equal pem, orig.public_to_pem assert_equal pem, key.public_to_pem end def test_pem_passwd omit_on_fips - key = Fixtures.pkey("rsa1024") + key = Fixtures.pkey("rsa-1") pem3c = key.to_pem("aes-128-cbc", "key") assert_match (/ENCRYPTED/), pem3c assert_equal key.to_der, OpenSSL::PKey.read(pem3c, "key").to_der @@ -493,90 +443,73 @@ class OpenSSL::TestPKeyRSA < OpenSSL::PKeyTestCase end def test_private_encoding - rsa1024 = Fixtures.pkey("rsa1024") + pkey = Fixtures.pkey("rsa-1") asn1 = OpenSSL::ASN1::Sequence([ OpenSSL::ASN1::Integer(0), OpenSSL::ASN1::Sequence([ OpenSSL::ASN1::ObjectId("rsaEncryption"), OpenSSL::ASN1::Null(nil) ]), - OpenSSL::ASN1::OctetString(rsa1024.to_der) + OpenSSL::ASN1::OctetString(pkey.to_der) ]) - assert_equal asn1.to_der, rsa1024.private_to_der - assert_same_rsa rsa1024, OpenSSL::PKey.read(asn1.to_der) + assert_equal asn1.to_der, pkey.private_to_der + assert_same_rsa pkey, OpenSSL::PKey.read(asn1.to_der) - pem = <<~EOF - -----BEGIN PRIVATE KEY----- - MIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBAMvCxLDUQKc+1P4+ - Q6AeFwYDvWfALb+cvzlUEadGoPE6qNWHsLFoo8RFgeyTgE8KQTduu1OE9Zz2SMcR - BDu5/1jWtsLPSVrI2ofLLBARUsWanVyki39DeB4u/xkP2mKGjAokPIwOI3oCthSZ - lzO9bj3voxTf6XngTqUX8l8URTmHAgMBAAECgYEApKX8xBqvJ7XI7Kypfo/x8MVC - 3rxW+1eQ2aVKIo4a7PKGjQz5RVIVyzqTUvSZoMTbkAxlSIbO5YfJpTnl3tFcOB6y - QMxqQPW/pl6Ni3EmRJdsRM5MsPBRZOfrXxOCdvXu1TWOS1S1TrvEr/TyL9eh2WCd - CGzpWgdO4KHce7vs7pECQQDv6DGoG5lHnvbvj9qSJb9K5ebRJc8S+LI7Uy5JHC0j - zsHTYPSqBXwPVQdGbgCEycnwwKzXzT2QxAQmJBQKun2ZAkEA2W3aeAE7Xi6zo2eG - 4Cx4UNMHMIdfBRS7VgoekwybGmcapqV0aBew5kHeWAmxP1WUZ/dgZh2QtM1VuiBA - qUqkHwJBAOJLCRvi/JB8N7z82lTk2i3R8gjyOwNQJv6ilZRMyZ9vFZFHcUE27zCf - Kb+bX03h8WPwupjMdfgpjShU+7qq8nECQQDBrmyc16QVyo40sgTgblyiysitvviy - ovwZsZv4q5MCmvOPnPUrwGbRRb2VONUOMOKpFiBl9lIv7HU//nj7FMVLAkBjUXED - 83dA8JcKM+HlioXEAxCzZVVhN+D63QwRwkN08xAPklfqDkcqccWDaZm2hdCtaYlK - funwYkrzI1OikQSs - -----END PRIVATE KEY----- - EOF - assert_equal pem, rsa1024.private_to_pem - assert_same_rsa rsa1024, OpenSSL::PKey.read(pem) + pem = der_to_pem(asn1.to_der, "PRIVATE KEY") + assert_equal pem, pkey.private_to_pem + assert_same_rsa pkey, OpenSSL::PKey.read(pem) end def test_private_encoding_encrypted rsa = Fixtures.pkey("rsa2048") - encoded = rsa.private_to_der("aes-128-cbc", "abcdef") + encoded = rsa.private_to_der("aes-128-cbc", "abcdefgh") asn1 = OpenSSL::ASN1.decode(encoded) # PKCS #8 EncryptedPrivateKeyInfo assert_kind_of OpenSSL::ASN1::Sequence, asn1 assert_equal 2, asn1.value.size assert_not_equal rsa.private_to_der, encoded - assert_same_rsa rsa, OpenSSL::PKey.read(encoded, "abcdef") - assert_same_rsa rsa, OpenSSL::PKey.read(encoded) { "abcdef" } + assert_same_rsa rsa, OpenSSL::PKey.read(encoded, "abcdefgh") + assert_same_rsa rsa, OpenSSL::PKey.read(encoded) { "abcdefgh" } assert_raise(OpenSSL::PKey::PKeyError) { OpenSSL::PKey.read(encoded, "abcxyz") } - encoded = rsa.private_to_pem("aes-128-cbc", "abcdef") + encoded = rsa.private_to_pem("aes-128-cbc", "abcdefgh") assert_match (/BEGIN ENCRYPTED PRIVATE KEY/), encoded.lines[0] - assert_same_rsa rsa, OpenSSL::PKey.read(encoded, "abcdef") + assert_same_rsa rsa, OpenSSL::PKey.read(encoded, "abcdefgh") # Use openssl instead of certtool due to https://gitlab.com/gnutls/gnutls/-/issues/1632 - # openssl pkcs8 -in test/openssl/fixtures/pkey/rsa2048.pem -topk8 -v2 aes-128-cbc -passout pass:abcdef + # openssl pkcs8 -in test/openssl/fixtures/pkey/rsa2048.pem -topk8 -v2 aes-128-cbc -passout pass:abcdefgh pem = <<~EOF - -----BEGIN ENCRYPTED PRIVATE KEY----- - MIIFLTBXBgkqhkiG9w0BBQ0wSjApBgkqhkiG9w0BBQwwHAQIay5V8CDQi5oCAggA - MAwGCCqGSIb3DQIJBQAwHQYJYIZIAWUDBAECBBB6eyagcbsvdQlM1kPcH7kiBIIE - 0Ng1apIyoPAZ4BfC4kMNeSmeAv3XspxqYi3uWzXiNyTcoE6390swrwM6WvdpXvLI - /n/V06krxPZ9X4fBG2kLUzXt5f09lEvmQU1HW1wJGU5Sq3bNeXBrlJF4DzJE4WWd - whVVvNMm44ghdzN/jGSw3z+6d717N+waa7vrpBDsHjhsPNwxpyzUvcFPFysTazxx - kN/dziIBF6SRKi6w8VaJEMQ8czGu5T3jOc2e/1p3/AYhHLPS4NHhLR5OUh0TKqLK - tANAqI9YqCAjhqcYCmN3mMQXY52VfOqG9hlX1x9ZQyqiH7l102EWbPqouk6bCBLQ - wHepPg4uK99Wsdh65qEryNnXQ5ZmO6aGb6T3TFENCaNKmi8Nh+/5dr7J7YfhIwpo - FqHvk0hrZ8r3EQlr8/td0Yb1/IKzeQ34638uXf9UxK7C6o+ilsmJDR4PHJUfZL23 - Yb9qWJ0GEzd5AMsI7x6KuUxSuH9nKniv5Tzyty3Xmb4FwXUyADWE19cVuaT+HrFz - GraKnA3UXbEgWAU48/l4K2HcAHyHDD2Kbp8k+o1zUkH0fWUdfE6OUGtx19Fv44Jh - B7xDngK8K48C6nrj06/DSYfXlb2X7WQiapeG4jt6U57tLH2XAjHCkvu0IBZ+//+P - yIWduEHQ3w8FBRcIsTNJo5CjkGk580TVQB/OBLWfX48Ay3oF9zgnomDIlVjl9D0n - lKxw/KMCLkvB78rUeGbr1Kwj36FhGpTBw3FgcYGa5oWFZTlcOgMTXLqlbb9JnDlA - Zs7Tu0WTyOTV/Dne9nEm39Dzu6wRojiIpmygTD4FI7rmOy3CYNvL3XPv7XQj0hny - Ee/fLxugYlQnwPZSqOVEQY2HsG7AmEHRsvy4bIWIGt+yzAPZixt9MUdJh91ttRt7 - QA/8J1pAsGqEuQpF6UUINZop3J7twfhO4zWYN/NNQ52eWNX2KLfjfGRhrvatzmZ0 - BuCsCI9hwEeE6PTlhbX1Rs177MrDc3vlqz2V3Po0OrFjXAyg9DR/OC4iK5wOG2ZD - 7StVSP8bzwQXsz3fJ0ardKXgnU2YDAP6Vykjgt+nFI09HV/S2faOc2g/UK4Y2khl - J93u/GHMz/Kr3bKWGY1/6nPdIdFheQjsiNhd5gI4tWik2B3QwU9mETToZ2LSvDHU - jYCys576xJLkdMM6nJdq72z4tCoES9IxyHVs4uLjHKIo/ZtKr+8xDo8IL4ax3U8+ - NMhs/lwReHmPGahm1fu9zLRbNCVL7e0zrOqbjvKcSEftObpV/LLcPYXtEm+lZcck - /PMw49HSE364anKEXCH1cyVWJwdZRpFUHvRpLIrpHru7/cthhiEMdLgK1/x8sLob - DiyieLxH1DPeXT4X+z94ER4IuPVOcV5AXc/omghispEX6DNUnn5jC4e3WyabjUbw - MuO9lVH9Wi2/ynExCqVmQkdbTXuLwjni1fJ27Q5zb0aCmhO8eq6P869NCjhJuiUj - NI9XtGLP50YVWE0kL8KEJqnyFudky8Khzk4/dyixQFqin5GfT4vetrLunGHy7lRB - 3LpnFrpMOr+0xr1RW1k9vlmjRsJSiojJfReYO7gH3B5swiww2azogoL+4jhF1Jxh - OYLWdkKhP2jSVGqtIDtny0O4lBm2+hLpWjiI0mJQ7wdA - -----END ENCRYPTED PRIVATE KEY----- +-----BEGIN ENCRYPTED PRIVATE KEY----- +MIIFNTBfBgkqhkiG9w0BBQ0wUjAxBgkqhkiG9w0BBQwwJAQQ+Sg92Hgy8EgVPf7t +Hen1qwICCAAwDAYIKoZIhvcNAgkFADAdBglghkgBZQMEAQIEEB5UX2xdDO8/AKA8 ++Y5CZyUEggTQkArh4mMPpnAe3xOcDKMz8KCn5lrLb/6Dla7Rp9LHKGkUfyI11EZt +m+OIriwy9oDQquKyVuLQVGAxXKk+3pyxMqLB0i3hLYamT3vzoPctyVwjuRuKoU3E +CbF0YhCoxvWMvjHsolwYzx00DbLXouE4BGKvPjnhw5hwtdoZ9Px0ZnCXCxVXi8z/ +mlw7a2ptKEiHQVjuPPbttq+dA+ez7pbWonWVod5TMaPtyEZu5XfPD+0pMboceHZg +H8ehgUhV3mzEJiisFGg1q9hj+4BaFl5m4tvqp43inCCdShE78CNnOPzJ7WCjKJqi +jGvHjeMoVx3rZXHcZDAzfIZvDigp9uAfzjRJjpRG8sg5sDQVC7vdUhQDe5TorKT2 +Vb0tdVYxoEpMJ3dhU6Ds5JxMR6GTLjsjTqOkAl6db3HxulwfEpr7YjOpfODR+ttA +BeIcUcMLsDHayIaQaMLIftHxOkfX7UxoFW9CMG5UMQf/m3eEgVUwgK/E5sUJRUTo +yhRzJ4NAP4fgc4YH9tbzvUrhfdCXCBEOn6IlDQL66SZr8Mm+Ggu4Ij4TnKWXLrXL +nSTDDa42kPOvtedKqxC/uXE7rrfh+uyw6J6OjSl6u86TIebndLuDo5DTdWKh8rsg +fvZZ6332dfMp8JC9/4YnYIJdI7acInSoyHp52OB+2+dgYCr5OrZFjjKS7nELVfo7 +OxGy6uH3NHF9qyUEf3MN17TRHI7jP3zKbXcDTPSyxLQkWe/CU5B251CTmoTSidSW +EhKnPlGZYbpVQJ4KGEL5UeY8W9PXQo4Dl7TmXBGvuPqNF8kMB3XrPIph7GmihmX0 +nlJqLk9eiRFmUETS0IdAyKJrm4R9Hf6rjYCbXlaApylyVUdSZ2BxgeoTY9BA6Kgf +3xlgMv01MoUkXMx2+OLIc9MzhButQiDxh3mfS012CjKqUFrJhRSa8DOpUfVgmXpq +/HP4drWamLWYJR8FsmJS11ZYc1EK/ctJTSpqfewvoUGOSHomhh7zXn1Acb6+9/3p +bcrJjoR5K8Jg6NlG4dSNkpY/x92I7bFLXFqELIH5tteDrlQen5eASjaiyPPAoOw8 +IGfOmFS4VUPh1VP6g8Jtn5Hr2qXB3DoQoI6EvUZhJ6GJfi67mx5VKux6G9MzJkix +GU1cL4WzWK2DU0l39UxXjS+4TmOYbrqLVnVMjusX0fwb8LkDC/fVohbhLwhHNwu6 +nSTSEpS9zSDrv1JXFtAtPv6XCSFs6ssPWJMwGSdThn7EfV0GEhG2mCzTyVhwxxQo +6U/Suqq4oMZoracPUCZx0E4u/bb4KBoFA/eBNPJENTR18IiV+D7wAxlxauO3N1t4 +iJxwrrvSgQPmOGuxrh5LVD41UXYUWLtndzabnpByppFn2MbmvrqJgon0MSs84cTA +7scnbPu1V3PpKy/t67gtVw9Ue8hLjrskWB1JPFYr7vRWvJzYjfbflyroF+QEJ3TA +6rTfUC9+ePci6T+i9jF4xcmzqYzRtnGtp5nRUitJGw0uwBTDwzfI2WD6ltvvu7lc +pHuzvY5zEapuu1JhjHLUd+OE8rVVM999DUXo/IDLsWyRCphCiYfVXJNogd9rB0Ta +5AhVgpRhxkarBURZyLTYj7NRxCsbHq7XExJNrIdRG/KlBQfyEyIzZ7E= +-----END ENCRYPTED PRIVATE KEY----- EOF - assert_same_rsa rsa, OpenSSL::PKey.read(pem, "abcdef") + assert_same_rsa rsa, OpenSSL::PKey.read(pem, "abcdefgh") end def test_params @@ -600,7 +533,7 @@ class OpenSSL::TestPKeyRSA < OpenSSL::PKeyTestCase end def test_dup - key = Fixtures.pkey("rsa1024") + key = Fixtures.pkey("rsa-1") key2 = key.dup assert_equal key.params, key2.params @@ -612,7 +545,7 @@ class OpenSSL::TestPKeyRSA < OpenSSL::PKeyTestCase end def test_marshal - key = Fixtures.pkey("rsa2048") + key = Fixtures.pkey("rsa-1") deserialized = Marshal.load(Marshal.dump(key)) assert_equal key.to_der, deserialized.to_der diff --git a/test/openssl/test_provider.rb b/test/openssl/test_provider.rb index 6f85c00c98..10081e208c 100644 --- a/test/openssl/test_provider.rb +++ b/test/openssl/test_provider.rb @@ -46,6 +46,7 @@ class OpenSSL::TestProvider < OpenSSL::TestCase with_openssl(<<-'end;') begin + OpenSSL::Provider.load("default") OpenSSL::Provider.load("legacy") rescue OpenSSL::Provider::ProviderError omit "Only for OpenSSL with legacy provider" diff --git a/test/openssl/test_ssl.rb b/test/openssl/test_ssl.rb index f1ce0b5dfc..e4fd581079 100644 --- a/test/openssl/test_ssl.rb +++ b/test/openssl/test_ssl.rb @@ -270,6 +270,11 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase ssl.syswrite(str) assert_same buf, ssl.sysread(str.size, buf) assert_equal(str, buf) + + obj = Object.new + obj.define_singleton_method(:to_str) { str } + ssl.syswrite(obj) + assert_equal(str, ssl.sysread(str.bytesize)) } } end @@ -350,6 +355,22 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase end end + def test_sync_close_initialize_opt + start_server do |port| + begin + sock = TCPSocket.new("127.0.0.1", port) + ssl = OpenSSL::SSL::SSLSocket.new(sock, sync_close: true) + assert_equal true, ssl.sync_close + ssl.connect + ssl.puts "abc"; assert_equal "abc\n", ssl.gets + ssl.close + assert_predicate sock, :closed? + ensure + sock&.close + end + end + end + def test_copy_stream start_server do |port| server_connect(port) do |ssl| @@ -680,6 +701,8 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase end def test_post_connect_check_with_anon_ciphers + # DH missing the q value on unknown named parameters is not FIPS-approved. + omit_on_fips omit "AWS-LC does not support DHE ciphersuites" if aws_lc? ctx_proc = -> ctx { @@ -1057,36 +1080,46 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase end end - def test_servername_cb_raises_an_exception_on_unknown_objects - hostname = 'example.org' - - ctx2 = OpenSSL::SSL::SSLContext.new - ctx2.cert = @svr_cert - ctx2.key = @svr_key - ctx2.servername_cb = lambda { |args| Object.new } - + def test_servername_cb_exception sock1, sock2 = socketpair + t = Thread.new { + s1 = OpenSSL::SSL::SSLSocket.new(sock1) + s1.hostname = "localhost" + assert_raise_with_message(OpenSSL::SSL::SSLError, /unrecognized.name/i) { + s1.connect + } + } + + ctx2 = OpenSSL::SSL::SSLContext.new + ctx2.servername_cb = lambda { |args| raise RuntimeError, "foo" } s2 = OpenSSL::SSL::SSLSocket.new(sock2, ctx2) + assert_raise_with_message(RuntimeError, "foo") { s2.accept } + assert t.join + ensure + sock1.close + sock2.close + t.kill.join + end - ctx1 = OpenSSL::SSL::SSLContext.new + def test_servername_cb_raises_an_exception_on_unknown_objects + sock1, sock2 = socketpair - s1 = OpenSSL::SSL::SSLSocket.new(sock1, ctx1) - s1.hostname = hostname t = Thread.new { - assert_raise(OpenSSL::SSL::SSLError) do - s1.connect - end + s1 = OpenSSL::SSL::SSLSocket.new(sock1) + s1.hostname = "localhost" + assert_raise(OpenSSL::SSL::SSLError) { s1.connect } } - assert_raise(ArgumentError) do - s2.accept - end - + ctx2 = OpenSSL::SSL::SSLContext.new + ctx2.servername_cb = lambda { |args| Object.new } + s2 = OpenSSL::SSL::SSLSocket.new(sock2, ctx2) + assert_raise(ArgumentError) { s2.accept } assert t.join ensure - sock1.close if sock1 - sock2.close if sock2 + sock1.close + sock2.close + t.kill.join end def test_accept_errors_include_peeraddr @@ -1742,6 +1775,9 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase end def test_get_ephemeral_key + # kRSA is not FIPS-approved. + omit_on_fips + # kRSA ctx_proc1 = proc { |ctx| ctx.max_version = OpenSSL::SSL::TLS1_2_VERSION @@ -1759,33 +1795,28 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase end end - if !aws_lc? # AWS-LC does not support DHE ciphersuites. - # DHE - # TODO: SSL_CTX_set1_groups() is required for testing this with TLS 1.3 - ctx_proc2 = proc { |ctx| - ctx.max_version = OpenSSL::SSL::TLS1_2_VERSION - ctx.ciphers = "EDH" - ctx.tmp_dh = Fixtures.pkey("dh-1") - } - start_server(ctx_proc: ctx_proc2) do |port| + # DHE + # OpenSSL 3.0 added support for named FFDHE groups in TLS 1.3 + # LibreSSL does not support named FFDHE groups currently + # AWS-LC does not support DHE ciphersuites + if openssl?(3, 0, 0) + start_server do |port| ctx = OpenSSL::SSL::SSLContext.new - ctx.max_version = OpenSSL::SSL::TLS1_2_VERSION - ctx.ciphers = "EDH" + ctx.groups = "ffdhe3072" server_connect(port, ctx) { |ssl| assert_instance_of OpenSSL::PKey::DH, ssl.tmp_key + assert_equal 3072, ssl.tmp_key.p.num_bits + ssl.puts "abc"; assert_equal "abc\n", ssl.gets } end end # ECDHE ctx_proc3 = proc { |ctx| - ctx.ciphers = "DEFAULT:!kRSA:!kEDH" - ctx.ecdh_curves = "P-256" + ctx.groups = "P-256" } start_server(ctx_proc: ctx_proc3) do |port| - ctx = OpenSSL::SSL::SSLContext.new - ctx.ciphers = "DEFAULT:!kRSA:!kEDH" - server_connect(port, ctx) { |ssl| + server_connect(port) { |ssl| assert_instance_of OpenSSL::PKey::EC, ssl.tmp_key ssl.puts "abc"; assert_equal "abc\n", ssl.gets } @@ -1863,6 +1894,8 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase end def test_tmp_dh_callback + # DH missing the q value on unknown named parameters is not FIPS-approved. + omit_on_fips omit "AWS-LC does not support DHE ciphersuites" if aws_lc? dh = Fixtures.pkey("dh-1") @@ -1876,7 +1909,9 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase } } start_server(ctx_proc: ctx_proc) do |port| - server_connect(port) { |ssl| + ctx = OpenSSL::SSL::SSLContext.new + ctx.groups = "P-256" # Exclude RFC 7919 groups + server_connect(port, ctx) { |ssl| assert called, "dh callback should be called" assert_equal dh.to_der, ssl.tmp_key.to_der } @@ -1963,6 +1998,157 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase ) { ssl_ctx.ciphers = 'BOGUS' } end + def test_sigalgs + omit "SSL_CTX_set1_sigalgs_list() not supported" if libressl? + + svr_exts = [ + ["keyUsage", "keyEncipherment,digitalSignature", true], + ["subjectAltName", "DNS:localhost", false], + ] + ecdsa_key = Fixtures.pkey("p256") + ecdsa_cert = issue_cert(@svr, ecdsa_key, 10, svr_exts, @ca_cert, @ca_key) + + ctx_proc = -> ctx { + # Unset values set by start_server + ctx.cert = ctx.key = ctx.extra_chain_cert = nil + ctx.add_certificate(@svr_cert, @svr_key, [@ca_cert]) # RSA + ctx.add_certificate(ecdsa_cert, ecdsa_key, [@ca_cert]) # ECDSA + } + start_server(ctx_proc: ctx_proc) do |port| + ctx1 = OpenSSL::SSL::SSLContext.new + ctx1.sigalgs = "rsa_pss_rsae_sha256" + server_connect(port, ctx1) { |ssl| + assert_kind_of(OpenSSL::PKey::RSA, ssl.peer_cert.public_key) + ssl.puts("abc"); ssl.gets + } + + ctx2 = OpenSSL::SSL::SSLContext.new + ctx2.sigalgs = "ed25519:ecdsa_secp256r1_sha256" + server_connect(port, ctx2) { |ssl| + assert_kind_of(OpenSSL::PKey::EC, ssl.peer_cert.public_key) + ssl.puts("abc"); ssl.gets + } + end + + # Frozen + ssl_ctx = OpenSSL::SSL::SSLContext.new + ssl_ctx.freeze + assert_raise(FrozenError) { ssl_ctx.sigalgs = "ECDSA+SHA256:RSA+SHA256" } + + # Bogus + ssl_ctx = OpenSSL::SSL::SSLContext.new + assert_raise(TypeError) { ssl_ctx.sigalgs = nil } + assert_raise(OpenSSL::SSL::SSLError) { ssl_ctx.sigalgs = "BOGUS" } + end + + def test_client_sigalgs + omit "SSL_CTX_set1_client_sigalgs_list() not supported" if libressl? || aws_lc? + + cli_exts = [ + ["keyUsage", "keyEncipherment,digitalSignature", true], + ["subjectAltName", "DNS:localhost", false], + ] + ecdsa_key = Fixtures.pkey("p256") + ecdsa_cert = issue_cert(@cli, ecdsa_key, 10, cli_exts, @ca_cert, @ca_key) + + ctx_proc = -> ctx { + store = OpenSSL::X509::Store.new + store.add_cert(@ca_cert) + store.purpose = OpenSSL::X509::PURPOSE_SSL_CLIENT + ctx.cert_store = store + ctx.verify_mode = OpenSSL::SSL::VERIFY_PEER|OpenSSL::SSL::VERIFY_FAIL_IF_NO_PEER_CERT + ctx.client_sigalgs = "ECDSA+SHA256" + } + start_server(ctx_proc: ctx_proc, ignore_listener_error: true) do |port| + ctx1 = OpenSSL::SSL::SSLContext.new + ctx1.add_certificate(@cli_cert, @cli_key) # RSA + assert_handshake_error { + server_connect(port, ctx1) { |ssl| + ssl.puts("abc"); ssl.gets + } + } + + ctx2 = OpenSSL::SSL::SSLContext.new + ctx2.add_certificate(ecdsa_cert, ecdsa_key) # ECDSA + server_connect(port, ctx2) { |ssl| + ssl.puts("abc"); ssl.gets + } + end + end + + def test_get_sigalg + # SSL_get0_signature_name() not supported + # SSL_get0_peer_signature_name() not supported + return unless openssl?(3, 5, 0) + + server_proc = -> (ctx, ssl) { + assert_equal('rsa_pss_rsae_sha256', ssl.sigalg) + assert_nil(ssl.peer_sigalg) + + readwrite_loop(ctx, ssl) + } + start_server(server_proc: server_proc) do |port| + cli_ctx = OpenSSL::SSL::SSLContext.new + server_connect(port, cli_ctx) do |ssl| + assert_nil(ssl.sigalg) + assert_equal('rsa_pss_rsae_sha256', ssl.peer_sigalg) + ssl.puts "abc"; ssl.gets + end + end + end + + def test_pqc_sigalg + # PQC algorithm ML-DSA (FIPS 204) is supported on OpenSSL 3.5 or later. + return unless openssl?(3, 5, 0) + + mldsa = Fixtures.pkey("mldsa65-1") + mldsa_ca_key = Fixtures.pkey("mldsa65-2") + mldsa_ca_cert = issue_cert(@ca, mldsa_ca_key, 1, @ca_exts, nil, nil, + digest: nil) + mldsa_cert = issue_cert(@svr, mldsa, 60, [], mldsa_ca_cert, mldsa_ca_key, + digest: nil) + rsa = Fixtures.pkey("rsa-1") + rsa_cert = issue_cert(@svr, rsa, 61, [], @ca_cert, @ca_key) + ctx_proc = -> ctx { + # Unset values set by start_server + ctx.cert = ctx.key = ctx.extra_chain_cert = nil + ctx.sigalgs = "rsa_pss_rsae_sha256:mldsa65" + ctx.add_certificate(mldsa_cert, mldsa) + ctx.add_certificate(rsa_cert, rsa) + } + + server_proc = -> (ctx, ssl) { + assert_equal('mldsa65', ssl.sigalg) + + readwrite_loop(ctx, ssl) + } + start_server(ctx_proc: ctx_proc, server_proc: server_proc) do |port| + ctx = OpenSSL::SSL::SSLContext.new + # Set signature algorithm because while OpenSSL may use ML-DSA by + # default, the system OpenSSL configuration affects the used signature + # algorithm. + ctx.sigalgs = 'mldsa65' + server_connect(port, ctx) { |ssl| + assert_equal('mldsa65', ssl.peer_sigalg) + ssl.puts "abc"; ssl.gets + } + end + + server_proc = -> (ctx, ssl) { + assert_equal('rsa_pss_rsae_sha256', ssl.sigalg) + + readwrite_loop(ctx, ssl) + } + start_server(ctx_proc: ctx_proc, server_proc: server_proc) do |port| + ctx = OpenSSL::SSL::SSLContext.new + ctx.sigalgs = 'rsa_pss_rsae_sha256' + server_connect(port, ctx) { |ssl| + assert_equal('rsa_pss_rsae_sha256', ssl.peer_sigalg) + ssl.puts "abc"; ssl.gets + } + end + end + def test_connect_works_when_setting_dh_callback_to_nil omit "AWS-LC does not support DHE ciphersuites" if aws_lc? @@ -1972,15 +2158,13 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase ctx.tmp_dh_callback = nil } start_server(ctx_proc: ctx_proc) do |port| - EnvUtil.suppress_warning { # uses default callback - assert_nothing_raised { - server_connect(port) { } - } - } + assert_nothing_raised { server_connect(port) { } } end end def test_tmp_dh + # DH missing the q value on unknown named parameters is not FIPS-approved. + omit_on_fips omit "AWS-LC does not support DHE ciphersuites" if aws_lc? dh = Fixtures.pkey("dh-1") @@ -1990,64 +2174,100 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase ctx.tmp_dh = dh } start_server(ctx_proc: ctx_proc) do |port| - server_connect(port) { |ssl| + ctx = OpenSSL::SSL::SSLContext.new + ctx.groups = "P-256" # Exclude RFC 7919 groups + server_connect(port, ctx) { |ssl| assert_equal dh.to_der, ssl.tmp_key.to_der } end end - def test_ecdh_curves_tls12 + def test_set_groups_tls12 ctx_proc = -> ctx { # Enable both ECDHE (~ TLS 1.2) cipher suites and TLS 1.3 ctx.max_version = OpenSSL::SSL::TLS1_2_VERSION ctx.ciphers = "kEECDH" - ctx.ecdh_curves = "P-384:P-521" + ctx.groups = "P-384:P-521" } start_server(ctx_proc: ctx_proc, ignore_listener_error: true) do |port| # Test 1: Client=P-256:P-384, Server=P-384:P-521 --> P-384 ctx = OpenSSL::SSL::SSLContext.new - ctx.ecdh_curves = "P-256:P-384" + ctx.groups = "P-256:P-384" server_connect(port, ctx) { |ssl| cs = ssl.cipher[0] assert_match (/\AECDH/), cs + # SSL_get0_group_name() is supported on OpenSSL 3.2 or later. + assert_equal "secp384r1", ssl.group if openssl?(3, 2, 0) assert_equal "secp384r1", ssl.tmp_key.group.curve_name ssl.puts "abc"; assert_equal "abc\n", ssl.gets } # Test 2: Client=P-256, Server=P-521:P-384 --> Fail ctx = OpenSSL::SSL::SSLContext.new - ctx.ecdh_curves = "P-256" + ctx.groups = "P-256" assert_raise(OpenSSL::SSL::SSLError) { server_connect(port, ctx) { } } # Test 3: Client=P-521:P-384, Server=P-521:P-384 --> P-521 ctx = OpenSSL::SSL::SSLContext.new - ctx.ecdh_curves = "P-521:P-384" + ctx.groups = "P-521:P-384" server_connect(port, ctx) { |ssl| assert_equal "secp521r1", ssl.tmp_key.group.curve_name ssl.puts "abc"; assert_equal "abc\n", ssl.gets } + + # Test 4: #ecdh_curves= alias + ctx = OpenSSL::SSL::SSLContext.new + ctx.ecdh_curves = "P-256:P-384" + server_connect(port, ctx) { |ssl| + assert_equal "secp384r1", ssl.tmp_key.group.curve_name + } end end - def test_ecdh_curves_tls13 + def test_set_groups_tls13 ctx_proc = -> ctx { # Assume TLS 1.3 is enabled and chosen by default - ctx.ecdh_curves = "P-384:P-521" + ctx.groups = "P-384:P-521" } start_server(ctx_proc: ctx_proc, ignore_listener_error: true) do |port| ctx = OpenSSL::SSL::SSLContext.new - ctx.ecdh_curves = "P-256:P-384" # disable P-521 + ctx.groups = "P-256:P-384" # disable P-521 server_connect(port, ctx) { |ssl| assert_equal "TLSv1.3", ssl.ssl_version + # SSL_get0_group_name() is supported on OpenSSL 3.2 or later. + assert_equal "secp384r1", ssl.group if openssl?(3, 2, 0) assert_equal "secp384r1", ssl.tmp_key.group.curve_name ssl.puts "abc"; assert_equal "abc\n", ssl.gets } end end + def test_pqc_group + # PQC algorithm ML-KEM (FIPS 203) is supported on OpenSSL 3.5 or later. + return unless openssl?(3, 5, 0) + + [ + 'X25519MLKEM768', + 'SecP256r1MLKEM768', + 'SecP384r1MLKEM1024' + ].each do |group| + ctx_proc = -> ctx { + ctx.groups = group + } + start_server(ctx_proc: ctx_proc) do |port| + ctx = OpenSSL::SSL::SSLContext.new + ctx.groups = group + server_connect(port, ctx) { |ssl| + assert_equal(group, ssl.group) + ssl.puts "abc"; ssl.gets + } + end + end + end + def test_security_level ctx = OpenSSL::SSL::SSLContext.new ctx.security_level = 1 @@ -2057,22 +2277,30 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase end assert_equal(1, ctx.security_level) - dsa512 = Fixtures.pkey("dsa512") - dsa512_cert = issue_cert(@svr, dsa512, 50, [], @ca_cert, @ca_key) - rsa1024 = Fixtures.pkey("rsa1024") - rsa1024_cert = issue_cert(@svr, rsa1024, 51, [], @ca_cert, @ca_key) + # See SSL_CTX_set_security_level(3). Definitions of security levels may + # change in future OpenSSL versions. As of OpenSSL 1.1.0: + # - Level 1 requires 160-bit ECC keys or 1024-bit RSA keys. + # - Level 2 requires 224-bit ECC keys or 2048-bit RSA keys. + begin + ec112 = OpenSSL::PKey::EC.generate("secp112r1") + ec112_cert = issue_cert(@svr, ec112, 50, [], @ca_cert, @ca_key) + ec192 = OpenSSL::PKey::EC.generate("prime192v1") + ec192_cert = issue_cert(@svr, ec192, 51, [], @ca_cert, @ca_key) + rescue OpenSSL::PKey::PKeyError + # Distro-provided OpenSSL may refuse to generate small keys + return + end assert_raise(OpenSSL::SSL::SSLError) { - # 512 bit DSA key is rejected because it offers < 80 bits of security - ctx.add_certificate(dsa512_cert, dsa512) + ctx.add_certificate(ec112_cert, ec112) } assert_nothing_raised { - ctx.add_certificate(rsa1024_cert, rsa1024) + ctx.add_certificate(ec192_cert, ec192) } ctx.security_level = 2 assert_raise(OpenSSL::SSL::SSLError) { # < 112 bits of security - ctx.add_certificate(rsa1024_cert, rsa1024) + ctx.add_certificate(ec192_cert, ec192) } end @@ -2128,6 +2356,50 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase end end + # OpenSSL::Buffering requires $/ accessible from non-main Ractors (Ruby 4.0) + # https://bugs.ruby-lang.org/issues/21109 + # + # Hangs on Windows + # https://bugs.ruby-lang.org/issues/21537 + if respond_to?(:ractor) && RUBY_VERSION >= "4.0" && RUBY_PLATFORM !~ /mswin|mingw/ + ractor + def test_ractor_client + start_server { |port| + s = Ractor.new(port, @ca_cert) { |port, ca_cert| + sock = TCPSocket.new("127.0.0.1", port) + ctx = OpenSSL::SSL::SSLContext.new + ctx.verify_mode = OpenSSL::SSL::VERIFY_PEER + ctx.cert_store = OpenSSL::X509::Store.new.tap { |store| + store.add_cert(ca_cert) + } + begin + ssl = OpenSSL::SSL::SSLSocket.new(sock, ctx) + ssl.connect + ssl.puts("abc") + ssl.gets + ensure + ssl.close + sock.close + end + }.value + assert_equal("abc\n", s) + } + end + + ractor + def test_ractor_set_params + # We cannot actually test default stores in the test suite as it depends + # on the environment, but at least check that it does not raise an + # exception + ok = Ractor.new { + ctx = OpenSSL::SSL::SSLContext.new + ctx.set_params + ctx.cert_store.kind_of?(OpenSSL::X509::Store) + }.value + assert(ok, "ctx.cert_store is an instance of OpenSSL::X509::Store") + end + end + private def server_connect(port, ctx = nil) diff --git a/test/openssl/test_ssl_session.rb b/test/openssl/test_ssl_session.rb index f453f58657..37874ca273 100644 --- a/test/openssl/test_ssl_session.rb +++ b/test/openssl/test_ssl_session.rb @@ -222,7 +222,7 @@ __EOS__ # Skipping tests that use session_remove_cb by default because it may cause # deadlock. - TEST_SESSION_REMOVE_CB = ENV["OSSL_TEST_ALL"] == "1" + TEST_SESSION_REMOVE_CB = ENV["OSSL_TEST_UNSAFE"] == "1" def test_ctx_client_session_cb_tls12 start_server do |port| diff --git a/test/openssl/test_ts.rb b/test/openssl/test_ts.rb index ac0469ad56..cca7898bc1 100644 --- a/test/openssl/test_ts.rb +++ b/test/openssl/test_ts.rb @@ -70,15 +70,14 @@ _end_of_pem_ def test_request_mandatory_fields req = OpenSSL::Timestamp::Request.new assert_raise(OpenSSL::Timestamp::TimestampError) do - tmp = req.to_der - pp OpenSSL::ASN1.decode(tmp) + req.to_der end req.algorithm = "sha1" assert_raise(OpenSSL::Timestamp::TimestampError) do req.to_der end req.message_imprint = OpenSSL::Digest.digest('SHA1', "data") - req.to_der + assert_nothing_raised { req.to_der } end def test_request_assignment @@ -89,8 +88,9 @@ _end_of_pem_ assert_raise(TypeError) { req.version = nil } assert_raise(TypeError) { req.version = "foo" } - req.algorithm = "SHA1" + req.algorithm = "sha1" assert_equal("SHA1", req.algorithm) + assert_equal("SHA1", OpenSSL::ASN1.ObjectId("SHA1").sn) assert_raise(TypeError) { req.algorithm = nil } assert_raise(OpenSSL::ASN1::ASN1Error) { req.algorithm = "xxx" } @@ -371,60 +371,60 @@ _end_of_pem_ end def test_response_no_policy_defined - assert_raise(OpenSSL::Timestamp::TimestampError) do - req = OpenSSL::Timestamp::Request.new - req.algorithm = "SHA1" - digest = OpenSSL::Digest.digest('SHA1', "test") - req.message_imprint = digest + req = OpenSSL::Timestamp::Request.new + req.algorithm = "SHA1" + digest = OpenSSL::Digest.digest('SHA1', "test") + req.message_imprint = digest - fac = OpenSSL::Timestamp::Factory.new - fac.gen_time = Time.now - fac.serial_number = 1 - fac.allowed_digests = ["sha1"] + fac = OpenSSL::Timestamp::Factory.new + fac.gen_time = Time.now + fac.serial_number = 1 + fac.allowed_digests = ["sha1"] + assert_raise(OpenSSL::Timestamp::TimestampError) do fac.create_timestamp(ee_key, ts_cert_ee, req) end end def test_verify_ee_no_req + ts, _ = timestamp_ee assert_raise(TypeError) do - ts, _ = timestamp_ee ts.verify(nil, ca_cert) end end def test_verify_ee_no_store + ts, req = timestamp_ee assert_raise(TypeError) do - ts, req = timestamp_ee ts.verify(req, nil) end end def test_verify_ee_wrong_root_no_intermediate + ts, req = timestamp_ee assert_raise(OpenSSL::Timestamp::TimestampError) do - ts, req = timestamp_ee ts.verify(req, intermediate_store) end end def test_verify_ee_wrong_root_wrong_intermediate + ts, req = timestamp_ee assert_raise(OpenSSL::Timestamp::TimestampError) do - ts, req = timestamp_ee ts.verify(req, intermediate_store, [ca_cert]) end end def test_verify_ee_nonce_mismatch + ts, req = timestamp_ee + req.nonce = 1 assert_raise(OpenSSL::Timestamp::TimestampError) do - ts, req = timestamp_ee - req.nonce = 1 ts.verify(req, ca_store, [intermediate_cert]) end end def test_verify_ee_intermediate_missing + ts, req = timestamp_ee assert_raise(OpenSSL::Timestamp::TimestampError) do - ts, req = timestamp_ee ts.verify(req, ca_store) end end @@ -472,27 +472,27 @@ _end_of_pem_ end def test_verify_direct_wrong_root + ts, req = timestamp_direct assert_raise(OpenSSL::Timestamp::TimestampError) do - ts, req = timestamp_direct ts.verify(req, intermediate_store) end end def test_verify_direct_no_cert_no_intermediate + ts, req = timestamp_direct_no_cert assert_raise(OpenSSL::Timestamp::TimestampError) do - ts, req = timestamp_direct_no_cert ts.verify(req, ca_store) end end def test_verify_ee_no_cert ts, req = timestamp_ee_no_cert - ts.verify(req, ca_store, [ts_cert_ee, intermediate_cert]) + assert_same(ts, ts.verify(req, ca_store, [ts_cert_ee, intermediate_cert])) end def test_verify_ee_no_cert_no_intermediate + ts, req = timestamp_ee_no_cert assert_raise(OpenSSL::Timestamp::TimestampError) do - ts, req = timestamp_ee_no_cert ts.verify(req, ca_store, [ts_cert_ee]) end end diff --git a/test/openssl/test_x509cert.rb b/test/openssl/test_x509cert.rb index 5fc87d9c67..9e0aa4edf6 100644 --- a/test/openssl/test_x509cert.rb +++ b/test/openssl/test_x509cert.rb @@ -6,17 +6,16 @@ if defined?(OpenSSL) class OpenSSL::TestX509Certificate < OpenSSL::TestCase def setup super - @rsa1024 = Fixtures.pkey("rsa1024") - @rsa2048 = Fixtures.pkey("rsa2048") - @dsa256 = Fixtures.pkey("dsa256") - @dsa512 = Fixtures.pkey("dsa512") + @rsa1 = Fixtures.pkey("rsa-1") + @rsa2 = Fixtures.pkey("rsa-2") + @ec1 = Fixtures.pkey("p256") @ca = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=CA") @ee1 = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=EE1") end def test_serial [1, 2**32, 2**100].each{|s| - cert = issue_cert(@ca, @rsa2048, s, [], nil, nil) + cert = issue_cert(@ca, @rsa1, s, [], nil, nil) assert_equal(s, cert.serial) cert = OpenSSL::X509::Certificate.new(cert.to_der) assert_equal(s, cert.serial) @@ -29,40 +28,34 @@ class OpenSSL::TestX509Certificate < OpenSSL::TestCase ["subjectKeyIdentifier","hash",false], ["authorityKeyIdentifier","keyid:always",false], ] - - [ - @rsa1024, @rsa2048, @dsa256, @dsa512, - ].each{|pk| - cert = issue_cert(@ca, pk, 1, exts, nil, nil) - assert_equal(cert.extensions.sort_by(&:to_s)[2].value, - OpenSSL::TestUtils.get_subject_key_id(cert)) - cert = OpenSSL::X509::Certificate.new(cert.to_der) - assert_equal(cert.extensions.sort_by(&:to_s)[2].value, - OpenSSL::TestUtils.get_subject_key_id(cert)) - } + cert = issue_cert(@ca, @rsa1, 1, exts, nil, nil) + assert_kind_of(OpenSSL::PKey::RSA, cert.public_key) + assert_equal(@rsa1.public_to_der, cert.public_key.public_to_der) + cert = OpenSSL::X509::Certificate.new(cert.to_der) + assert_equal(@rsa1.public_to_der, cert.public_key.public_to_der) end def test_validity now = Time.at(Time.now.to_i + 0.9) - cert = issue_cert(@ca, @rsa2048, 1, [], nil, nil, + cert = issue_cert(@ca, @rsa1, 1, [], nil, nil, not_before: now, not_after: now+3600) assert_equal(Time.at(now.to_i), cert.not_before) assert_equal(Time.at(now.to_i+3600), cert.not_after) now = Time.at(now.to_i) - cert = issue_cert(@ca, @rsa2048, 1, [], nil, nil, + cert = issue_cert(@ca, @rsa1, 1, [], nil, nil, not_before: now, not_after: now+3600) assert_equal(now.getutc, cert.not_before) assert_equal((now+3600).getutc, cert.not_after) now = Time.at(0) - cert = issue_cert(@ca, @rsa2048, 1, [], nil, nil, + cert = issue_cert(@ca, @rsa1, 1, [], nil, nil, not_before: now, not_after: now) assert_equal(now.getutc, cert.not_before) assert_equal(now.getutc, cert.not_after) now = Time.at(0x7fffffff) - cert = issue_cert(@ca, @rsa2048, 1, [], nil, nil, + cert = issue_cert(@ca, @rsa1, 1, [], nil, nil, not_before: now, not_after: now) assert_equal(now.getutc, cert.not_before) assert_equal(now.getutc, cert.not_after) @@ -75,7 +68,7 @@ class OpenSSL::TestX509Certificate < OpenSSL::TestCase ["subjectKeyIdentifier","hash",false], ["authorityKeyIdentifier","issuer:always,keyid:always",false], ] - ca_cert = issue_cert(@ca, @rsa2048, 1, ca_exts, nil, nil) + ca_cert = issue_cert(@ca, @rsa1, 1, ca_exts, nil, nil) ca_cert.extensions.each_with_index{|ext, i| assert_equal(ca_exts[i].first, ext.oid) assert_equal(ca_exts[i].last, ext.critical?) @@ -88,7 +81,7 @@ class OpenSSL::TestX509Certificate < OpenSSL::TestCase ["extendedKeyUsage","clientAuth, emailProtection, codeSigning",false], ["subjectAltName","email:ee1@ruby-lang.org",false], ] - ee1_cert = issue_cert(@ee1, @rsa1024, 2, ee1_exts, ca_cert, @rsa2048) + ee1_cert = issue_cert(@ee1, @rsa2, 2, ee1_exts, ca_cert, @rsa1) assert_equal(ca_cert.subject.to_der, ee1_cert.issuer.to_der) ee1_cert.extensions.each_with_index{|ext, i| assert_equal(ee1_exts[i].first, ext.oid) @@ -97,25 +90,25 @@ class OpenSSL::TestX509Certificate < OpenSSL::TestCase end def test_akiski - ca_cert = generate_cert(@ca, @rsa2048, 4, nil) + ca_cert = generate_cert(@ca, @rsa1, 4, nil) ef = OpenSSL::X509::ExtensionFactory.new(ca_cert, ca_cert) ca_cert.add_extension( ef.create_extension("subjectKeyIdentifier", "hash", false)) ca_cert.add_extension( ef.create_extension("authorityKeyIdentifier", "issuer:always,keyid:always", false)) - ca_cert.sign(@rsa2048, "sha256") + ca_cert.sign(@rsa1, "sha256") ca_keyid = get_subject_key_id(ca_cert.to_der, hex: false) assert_equal ca_keyid, ca_cert.authority_key_identifier assert_equal ca_keyid, ca_cert.subject_key_identifier - ee_cert = generate_cert(@ee1, Fixtures.pkey("p256"), 5, ca_cert) + ee_cert = generate_cert(@ee1, @rsa2, 5, ca_cert) ef = OpenSSL::X509::ExtensionFactory.new(ca_cert, ee_cert) ee_cert.add_extension( ef.create_extension("subjectKeyIdentifier", "hash", false)) ee_cert.add_extension( ef.create_extension("authorityKeyIdentifier", "issuer:always,keyid:always", false)) - ee_cert.sign(@rsa2048, "sha256") + ee_cert.sign(@rsa1, "sha256") ee_keyid = get_subject_key_id(ee_cert.to_der, hex: false) assert_equal ca_keyid, ee_cert.authority_key_identifier @@ -123,13 +116,13 @@ class OpenSSL::TestX509Certificate < OpenSSL::TestCase end def test_akiski_missing - cert = issue_cert(@ee1, @rsa2048, 1, [], nil, nil) + cert = issue_cert(@ee1, @rsa1, 1, [], nil, nil) assert_nil(cert.authority_key_identifier) assert_nil(cert.subject_key_identifier) end def test_crl_uris_no_crl_distribution_points - cert = issue_cert(@ee1, @rsa2048, 1, [], nil, nil) + cert = issue_cert(@ee1, @rsa1, 1, [], nil, nil) assert_nil(cert.crl_uris) end @@ -141,10 +134,10 @@ class OpenSSL::TestX509Certificate < OpenSSL::TestCase URI.1 = http://www.example.com/crl URI.2 = ldap://ldap.example.com/cn=ca?certificateRevocationList;binary _cnf_ - cdp_cert = generate_cert(@ee1, @rsa2048, 3, nil) + cdp_cert = generate_cert(@ee1, @rsa1, 3, nil) ef.subject_certificate = cdp_cert cdp_cert.add_extension(ef.create_extension("crlDistributionPoints", "@crlDistPts")) - cdp_cert.sign(@rsa2048, "sha256") + cdp_cert.sign(@rsa1, "sha256") assert_equal( ["http://www.example.com/crl", "ldap://ldap.example.com/cn=ca?certificateRevocationList;binary"], cdp_cert.crl_uris @@ -158,10 +151,10 @@ class OpenSSL::TestX509Certificate < OpenSSL::TestCase [crlDistPts_section] fullname = URI:http://www.example.com/crl, URI:ldap://ldap.example.com/cn=ca?certificateRevocationList;binary _cnf_ - cdp_cert = generate_cert(@ee1, @rsa2048, 3, nil) + cdp_cert = generate_cert(@ee1, @rsa1, 3, nil) ef.subject_certificate = cdp_cert cdp_cert.add_extension(ef.create_extension("crlDistributionPoints", "crlDistPts_section")) - cdp_cert.sign(@rsa2048, "sha256") + cdp_cert.sign(@rsa1, "sha256") assert_equal( ["http://www.example.com/crl", "ldap://ldap.example.com/cn=ca?certificateRevocationList;binary"], cdp_cert.crl_uris @@ -177,22 +170,22 @@ class OpenSSL::TestX509Certificate < OpenSSL::TestCase [dirname_section] CN = dirname _cnf_ - cdp_cert = generate_cert(@ee1, @rsa2048, 3, nil) + cdp_cert = generate_cert(@ee1, @rsa1, 3, nil) ef.subject_certificate = cdp_cert cdp_cert.add_extension(ef.create_extension("crlDistributionPoints", "crlDistPts_section")) - cdp_cert.sign(@rsa2048, "sha256") + cdp_cert.sign(@rsa1, "sha256") assert_nil(cdp_cert.crl_uris) end def test_aia_missing - cert = issue_cert(@ee1, @rsa2048, 1, [], nil, nil) + cert = issue_cert(@ee1, @rsa1, 1, [], nil, nil) assert_nil(cert.ca_issuer_uris) assert_nil(cert.ocsp_uris) end def test_aia ef = OpenSSL::X509::ExtensionFactory.new - aia_cert = generate_cert(@ee1, @rsa2048, 4, nil) + aia_cert = generate_cert(@ee1, @rsa1, 4, nil) ef.subject_certificate = aia_cert aia_cert.add_extension( ef.create_extension( @@ -204,7 +197,7 @@ class OpenSSL::TestX509Certificate < OpenSSL::TestCase false ) ) - aia_cert.sign(@rsa2048, "sha256") + aia_cert.sign(@rsa1, "sha256") assert_equal( ["http://www.example.com/caIssuers", "ldap://ldap.example.com/cn=ca?authorityInfoAccessCaIssuers;binary"], aia_cert.ca_issuer_uris @@ -217,7 +210,7 @@ class OpenSSL::TestX509Certificate < OpenSSL::TestCase def test_invalid_extension integer = OpenSSL::ASN1::Integer.new(0) - invalid_exts_cert = generate_cert(@ee1, @rsa1024, 1, nil) + invalid_exts_cert = generate_cert(@ee1, @rsa1, 1, nil) ["subjectKeyIdentifier", "authorityKeyIdentifier", "crlDistributionPoints", "authorityInfoAccess"].each do |ext| invalid_exts_cert.add_extension( OpenSSL::X509::Extension.new(ext, integer.to_der) @@ -241,57 +234,17 @@ class OpenSSL::TestX509Certificate < OpenSSL::TestCase } end - def test_sign_and_verify_rsa_sha1 - cert = issue_cert(@ca, @rsa2048, 1, [], nil, nil, digest: "SHA1") - assert_equal(false, cert.verify(@rsa1024)) - assert_equal(true, cert.verify(@rsa2048)) - assert_equal(false, certificate_error_returns_false { cert.verify(@dsa256) }) - assert_equal(false, certificate_error_returns_false { cert.verify(@dsa512) }) + def test_sign_and_verify + cert = issue_cert(@ca, @rsa1, 1, [], nil, nil, digest: "SHA256") + assert_equal("sha256WithRSAEncryption", cert.signature_algorithm) # ln + assert_equal(true, cert.verify(@rsa1)) + assert_equal(false, cert.verify(@rsa2)) + assert_equal(false, certificate_error_returns_false { cert.verify(@ec1) }) cert.serial = 2 - assert_equal(false, cert.verify(@rsa2048)) - rescue OpenSSL::X509::CertificateError # RHEL 9 disables SHA1 - end - - def test_sign_and_verify_rsa_md5 - cert = issue_cert(@ca, @rsa2048, 1, [], nil, nil, digest: "md5") - assert_equal(false, cert.verify(@rsa1024)) - assert_equal(true, cert.verify(@rsa2048)) - - assert_equal(false, certificate_error_returns_false { cert.verify(@dsa256) }) - assert_equal(false, certificate_error_returns_false { cert.verify(@dsa512) }) - cert.subject = @ee1 - assert_equal(false, cert.verify(@rsa2048)) - rescue OpenSSL::X509::CertificateError # RHEL7 disables MD5 - end - - def test_sign_and_verify_dsa - cert = issue_cert(@ca, @dsa512, 1, [], nil, nil) - assert_equal(false, certificate_error_returns_false { cert.verify(@rsa1024) }) - assert_equal(false, certificate_error_returns_false { cert.verify(@rsa2048) }) - assert_equal(false, cert.verify(@dsa256)) - assert_equal(true, cert.verify(@dsa512)) - cert.not_after = Time.now - assert_equal(false, cert.verify(@dsa512)) + assert_equal(false, cert.verify(@rsa1)) end - def test_sign_and_verify_rsa_dss1 - cert = issue_cert(@ca, @rsa2048, 1, [], nil, nil, digest: OpenSSL::Digest.new('DSS1')) - assert_equal(false, cert.verify(@rsa1024)) - assert_equal(true, cert.verify(@rsa2048)) - assert_equal(false, certificate_error_returns_false { cert.verify(@dsa256) }) - assert_equal(false, certificate_error_returns_false { cert.verify(@dsa512) }) - cert.subject = @ee1 - assert_equal(false, cert.verify(@rsa2048)) - rescue OpenSSL::X509::CertificateError - end if defined?(OpenSSL::Digest::DSS1) - - def test_sign_and_verify_dsa_md5 - assert_raise(OpenSSL::X509::CertificateError){ - issue_cert(@ca, @dsa512, 1, [], nil, nil, digest: "md5") - } - end - - def test_sign_and_verify_ed25519 + def test_sign_and_verify_nil_digest # Ed25519 is not FIPS-approved. omit_on_fips ed25519 = OpenSSL::PKey::generate_key("ED25519") @@ -299,24 +252,13 @@ class OpenSSL::TestX509Certificate < OpenSSL::TestCase assert_equal(true, cert.verify(ed25519)) end - def test_dsa_with_sha2 - cert = issue_cert(@ca, @dsa256, 1, [], nil, nil, digest: "sha256") - assert_equal("dsa_with_SHA256", cert.signature_algorithm) - # TODO: need more tests for dsa + sha2 - - # SHA1 is allowed from OpenSSL 1.0.0 (0.9.8 requires DSS1) - cert = issue_cert(@ca, @dsa256, 1, [], nil, nil, digest: "sha1") - assert_equal("dsaWithSHA1", cert.signature_algorithm) - rescue OpenSSL::X509::CertificateError # RHEL 9 disables SHA1 - end - def test_check_private_key - cert = issue_cert(@ca, @rsa2048, 1, [], nil, nil) - assert_equal(true, cert.check_private_key(@rsa2048)) + cert = issue_cert(@ca, @rsa1, 1, [], nil, nil) + assert_equal(true, cert.check_private_key(@rsa1)) end def test_read_from_file - cert = issue_cert(@ca, @rsa2048, 1, [], nil, nil) + cert = issue_cert(@ca, @rsa1, 1, [], nil, nil) Tempfile.create("cert") { |f| f << cert.to_pem f.rewind @@ -325,12 +267,12 @@ class OpenSSL::TestX509Certificate < OpenSSL::TestCase end def test_read_der_then_pem - cert1 = issue_cert(@ca, @rsa2048, 1, [], nil, nil) + cert1 = issue_cert(@ca, @rsa1, 1, [], nil, nil) exts = [ # A new line before PEM block ["nsComment", "Another certificate:\n" + cert1.to_pem], ] - cert2 = issue_cert(@ca, @rsa2048, 2, exts, nil, nil) + cert2 = issue_cert(@ca, @rsa1, 2, exts, nil, nil) assert_equal cert2, OpenSSL::X509::Certificate.new(cert2.to_der) assert_equal cert2, OpenSSL::X509::Certificate.new(cert2.to_pem) @@ -338,15 +280,15 @@ class OpenSSL::TestX509Certificate < OpenSSL::TestCase def test_eq now = Time.now - cacert = issue_cert(@ca, @rsa1024, 1, [], nil, nil, + cacert = issue_cert(@ca, @rsa1, 1, [], nil, nil, not_before: now, not_after: now + 3600) - cert1 = issue_cert(@ee1, @rsa2048, 2, [], cacert, @rsa1024, + cert1 = issue_cert(@ee1, @rsa2, 2, [], cacert, @rsa1, not_before: now, not_after: now + 3600) - cert2 = issue_cert(@ee1, @rsa2048, 2, [], cacert, @rsa1024, + cert2 = issue_cert(@ee1, @rsa2, 2, [], cacert, @rsa1, not_before: now, not_after: now + 3600) - cert3 = issue_cert(@ee1, @rsa2048, 3, [], cacert, @rsa1024, + cert3 = issue_cert(@ee1, @rsa2, 3, [], cacert, @rsa1, not_before: now, not_after: now + 3600) - cert4 = issue_cert(@ee1, @rsa2048, 2, [], cacert, @rsa1024, + cert4 = issue_cert(@ee1, @rsa2, 2, [], cacert, @rsa1, digest: "sha512", not_before: now, not_after: now + 3600) assert_equal false, cert1 == 12345 @@ -356,11 +298,19 @@ class OpenSSL::TestX509Certificate < OpenSSL::TestCase assert_equal false, cert3 == cert4 end + def test_inspect + cacert = issue_cert(@ca, @rsa1, 1, [], nil, nil) + assert_include(cacert.inspect, "subject=#{@ca.inspect}") + + # Do not raise an exception for an invalid certificate + assert_instance_of(String, OpenSSL::X509::Certificate.new.inspect) + end + def test_marshal now = Time.now - cacert = issue_cert(@ca, @rsa1024, 1, [], nil, nil, + cacert = issue_cert(@ca, @rsa1, 1, [], nil, nil, not_before: now, not_after: now + 3600) - cert = issue_cert(@ee1, @rsa2048, 2, [], cacert, @rsa1024, + cert = issue_cert(@ee1, @rsa2, 2, [], cacert, @rsa1, not_before: now, not_after: now + 3600) deserialized = Marshal.load(Marshal.dump(cert)) @@ -378,8 +328,8 @@ class OpenSSL::TestX509Certificate < OpenSSL::TestCase end def test_load_file_fullchain_pem - cert1 = issue_cert(@ee1, @rsa2048, 1, [], nil, nil) - cert2 = issue_cert(@ca, @rsa2048, 1, [], nil, nil) + cert1 = issue_cert(@ee1, @rsa1, 1, [], nil, nil) + cert2 = issue_cert(@ca, @rsa2, 1, [], nil, nil) Tempfile.create("fullchain.pem") do |f| f.puts cert1.to_pem @@ -394,7 +344,7 @@ class OpenSSL::TestX509Certificate < OpenSSL::TestCase end def test_load_file_certificate_der - cert = issue_cert(@ca, @rsa2048, 1, [], nil, nil) + cert = issue_cert(@ca, @rsa1, 1, [], nil, nil) Tempfile.create("certificate.der", binmode: true) do |f| f.write cert.to_der f.close @@ -419,7 +369,7 @@ class OpenSSL::TestX509Certificate < OpenSSL::TestCase end def test_tbs_precert_bytes - cert = issue_cert(@ca, @rsa2048, 1, [], nil, nil) + cert = issue_cert(@ca, @rsa1, 1, [], nil, nil) seq = OpenSSL::ASN1.decode(cert.tbs_bytes) assert_equal 7, seq.value.size diff --git a/test/openssl/test_x509crl.rb b/test/openssl/test_x509crl.rb index 89165388db..81c9247df2 100644 --- a/test/openssl/test_x509crl.rb +++ b/test/openssl/test_x509crl.rb @@ -6,25 +6,21 @@ if defined?(OpenSSL) class OpenSSL::TestX509CRL < OpenSSL::TestCase def setup super - @rsa1024 = Fixtures.pkey("rsa1024") - @rsa2048 = Fixtures.pkey("rsa2048") - @dsa256 = Fixtures.pkey("dsa256") - @dsa512 = Fixtures.pkey("dsa512") + @rsa1 = Fixtures.pkey("rsa-1") + @rsa2 = Fixtures.pkey("rsa-2") @ca = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=CA") - @ee1 = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=EE1") - @ee2 = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=EE2") end def test_basic now = Time.at(Time.now.to_i) - cert = issue_cert(@ca, @rsa2048, 1, [], nil, nil) - crl = issue_crl([], 1, now, now+1600, [], - cert, @rsa2048, OpenSSL::Digest.new('SHA256')) + cert = issue_cert(@ca, @rsa1, 1, [], nil, nil) + crl = issue_crl([], 1, now, now+1600, [], cert, @rsa1, "SHA256") assert_equal(1, crl.version) assert_equal(cert.issuer.to_der, crl.issuer.to_der) assert_equal(now, crl.last_update) assert_equal(now+1600, crl.next_update) + assert_equal("sha256WithRSAEncryption", crl.signature_algorithm) # ln crl = OpenSSL::X509::CRL.new(crl.to_der) assert_equal(1, crl.version) @@ -55,9 +51,9 @@ class OpenSSL::TestX509CRL < OpenSSL::TestCase [4, now, 4], [5, now, 5], ] - cert = issue_cert(@ca, @rsa2048, 1, [], nil, nil) + cert = issue_cert(@ca, @rsa1, 1, [], nil, nil) crl = issue_crl(revoke_info, 1, Time.now, Time.now+1600, [], - cert, @rsa2048, OpenSSL::Digest.new('SHA256')) + cert, @rsa1, "SHA256") revoked = crl.revoked assert_equal(5, revoked.size) assert_equal(1, revoked[0].serial) @@ -98,7 +94,7 @@ class OpenSSL::TestX509CRL < OpenSSL::TestCase revoke_info = (1..1000).collect{|i| [i, now, 0] } crl = issue_crl(revoke_info, 1, Time.now, Time.now+1600, [], - cert, @rsa2048, OpenSSL::Digest.new('SHA256')) + cert, @rsa1, "SHA256") revoked = crl.revoked assert_equal(1000, revoked.size) assert_equal(1, revoked[0].serial) @@ -122,9 +118,9 @@ class OpenSSL::TestX509CRL < OpenSSL::TestCase ["issuerAltName", "issuer:copy", false], ] - cert = issue_cert(@ca, @rsa2048, 1, cert_exts, nil, nil) + cert = issue_cert(@ca, @rsa1, 1, cert_exts, nil, nil) crl = issue_crl([], 1, Time.now, Time.now+1600, crl_exts, - cert, @rsa2048, OpenSSL::Digest.new('SHA256')) + cert, @rsa1, "SHA256") exts = crl.extensions assert_equal(3, exts.size) assert_equal("1", exts[0].value) @@ -160,59 +156,55 @@ class OpenSSL::TestX509CRL < OpenSSL::TestCase assert_equal(false, exts[2].critical?) no_ext_crl = issue_crl([], 1, Time.now, Time.now+1600, [], - cert, @rsa2048, OpenSSL::Digest.new('SHA256')) + cert, @rsa1, "SHA256") assert_equal nil, no_ext_crl.authority_key_identifier end def test_crlnumber - cert = issue_cert(@ca, @rsa2048, 1, [], nil, nil) - crl = issue_crl([], 1, Time.now, Time.now+1600, [], - cert, @rsa2048, OpenSSL::Digest.new('SHA256')) + cert = issue_cert(@ca, @rsa1, 1, [], nil, nil) + crl = issue_crl([], 1, Time.now, Time.now+1600, [], cert, @rsa1, "SHA256") assert_match(1.to_s, crl.extensions[0].value) assert_match(/X509v3 CRL Number:\s+#{1}/m, crl.to_text) crl = issue_crl([], 2**32, Time.now, Time.now+1600, [], - cert, @rsa2048, OpenSSL::Digest.new('SHA256')) + cert, @rsa1, "SHA256") assert_match((2**32).to_s, crl.extensions[0].value) assert_match(/X509v3 CRL Number:\s+#{2**32}/m, crl.to_text) crl = issue_crl([], 2**100, Time.now, Time.now+1600, [], - cert, @rsa2048, OpenSSL::Digest.new('SHA256')) + cert, @rsa1, "SHA256") assert_match(/X509v3 CRL Number:\s+#{2**100}/m, crl.to_text) assert_match((2**100).to_s, crl.extensions[0].value) end def test_sign_and_verify - cert = issue_cert(@ca, @rsa2048, 1, [], nil, nil) - crl = issue_crl([], 1, Time.now, Time.now+1600, [], - cert, @rsa2048, OpenSSL::Digest.new('SHA256')) - assert_equal(false, crl.verify(@rsa1024)) - assert_equal(true, crl.verify(@rsa2048)) - assert_equal(false, crl_error_returns_false { crl.verify(@dsa256) }) - assert_equal(false, crl_error_returns_false { crl.verify(@dsa512) }) + p256 = Fixtures.pkey("p256") + + cert = issue_cert(@ca, @rsa1, 1, [], nil, nil) + crl = issue_crl([], 1, Time.now, Time.now+1600, [], cert, @rsa1, "SHA256") + assert_equal(true, crl.verify(@rsa1)) + assert_equal(false, crl.verify(@rsa2)) + assert_equal(false, crl_error_returns_false { crl.verify(p256) }) crl.version = 0 - assert_equal(false, crl.verify(@rsa2048)) + assert_equal(false, crl.verify(@rsa1)) - cert = issue_cert(@ca, @dsa512, 1, [], nil, nil) - crl = issue_crl([], 1, Time.now, Time.now+1600, [], - cert, @dsa512, OpenSSL::Digest.new('SHA256')) - assert_equal(false, crl_error_returns_false { crl.verify(@rsa1024) }) - assert_equal(false, crl_error_returns_false { crl.verify(@rsa2048) }) - assert_equal(false, crl.verify(@dsa256)) - assert_equal(true, crl.verify(@dsa512)) + cert = issue_cert(@ca, p256, 1, [], nil, nil) + crl = issue_crl([], 1, Time.now, Time.now+1600, [], cert, p256, "SHA256") + assert_equal(false, crl_error_returns_false { crl.verify(@rsa1) }) + assert_equal(false, crl_error_returns_false { crl.verify(@rsa2) }) + assert_equal(true, crl.verify(p256)) crl.version = 0 - assert_equal(false, crl.verify(@dsa512)) + assert_equal(false, crl.verify(p256)) end - def test_sign_and_verify_ed25519 + def test_sign_and_verify_nil_digest # Ed25519 is not FIPS-approved. omit_on_fips ed25519 = OpenSSL::PKey::generate_key("ED25519") cert = issue_cert(@ca, ed25519, 1, [], nil, nil, digest: nil) crl = issue_crl([], 1, Time.now, Time.now+1600, [], cert, ed25519, nil) - assert_equal(false, crl_error_returns_false { crl.verify(@rsa1024) }) - assert_equal(false, crl_error_returns_false { crl.verify(@rsa2048) }) + assert_equal(false, crl_error_returns_false { crl.verify(@rsa1) }) assert_equal(false, crl.verify(OpenSSL::PKey::generate_key("ED25519"))) assert_equal(true, crl.verify(ed25519)) crl.version = 0 @@ -245,8 +237,8 @@ class OpenSSL::TestX509CRL < OpenSSL::TestCase def test_eq now = Time.now - cacert = issue_cert(@ca, @rsa1024, 1, [], nil, nil) - crl1 = issue_crl([], 1, now, now + 3600, [], cacert, @rsa1024, "sha256") + cacert = issue_cert(@ca, @rsa1, 1, [], nil, nil) + crl1 = issue_crl([], 1, now, now + 3600, [], cacert, @rsa1, "SHA256") rev1 = OpenSSL::X509::Revoked.new.tap { |rev| rev.serial = 1 rev.time = now @@ -274,8 +266,8 @@ class OpenSSL::TestX509CRL < OpenSSL::TestCase def test_marshal now = Time.now - cacert = issue_cert(@ca, @rsa1024, 1, [], nil, nil) - crl = issue_crl([], 1, now, now + 3600, [], cacert, @rsa1024, "sha256") + cacert = issue_cert(@ca, @rsa1, 1, [], nil, nil) + crl = issue_crl([], 1, now, now + 3600, [], cacert, @rsa1, "SHA256") rev = OpenSSL::X509::Revoked.new.tap { |rev| rev.serial = 1 rev.time = now diff --git a/test/openssl/test_x509name.rb b/test/openssl/test_x509name.rb index c6d15219f5..223c575e4e 100644 --- a/test/openssl/test_x509name.rb +++ b/test/openssl/test_x509name.rb @@ -423,24 +423,14 @@ class OpenSSL::TestX509Name < OpenSSL::TestCase assert_equal(nil, n3 <=> nil) end - def name_hash(name) - # OpenSSL 1.0.0 uses SHA1 for canonical encoding (not just a der) of - # X509Name for X509_NAME_hash. - name.respond_to?(:hash_old) ? name.hash_old : name.hash - end + def test_hash_old + omit_on_fips # MD5 - def test_hash dn = "/DC=org/DC=ruby-lang/CN=www.ruby-lang.org" name = OpenSSL::X509::Name.parse(dn) d = OpenSSL::Digest.digest('MD5', name.to_der) expected = (d[0].ord & 0xff) | (d[1].ord & 0xff) << 8 | (d[2].ord & 0xff) << 16 | (d[3].ord & 0xff) << 24 - assert_equal(expected, name_hash(name)) - # - dn = "/DC=org/DC=ruby-lang/CN=baz.ruby-lang.org" - name = OpenSSL::X509::Name.parse(dn) - d = OpenSSL::Digest.digest('MD5', name.to_der) - expected = (d[0].ord & 0xff) | (d[1].ord & 0xff) << 8 | (d[2].ord & 0xff) << 16 | (d[3].ord & 0xff) << 24 - assert_equal(expected, name_hash(name)) + assert_equal(expected, name.hash_old) end def test_equality diff --git a/test/openssl/test_x509req.rb b/test/openssl/test_x509req.rb index 18d3e7f8f3..b198a1185a 100644 --- a/test/openssl/test_x509req.rb +++ b/test/openssl/test_x509req.rb @@ -6,10 +6,8 @@ if defined?(OpenSSL) class OpenSSL::TestX509Request < OpenSSL::TestCase def setup super - @rsa1024 = Fixtures.pkey("rsa1024") - @rsa2048 = Fixtures.pkey("rsa2048") - @dsa256 = Fixtures.pkey("dsa256") - @dsa512 = Fixtures.pkey("dsa512") + @rsa1 = Fixtures.pkey("rsa-1") + @rsa2 = Fixtures.pkey("rsa-2") @dn = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=GOTOU Yuuzou") end @@ -23,31 +21,32 @@ class OpenSSL::TestX509Request < OpenSSL::TestCase end def test_public_key - req = issue_csr(0, @dn, @rsa1024, OpenSSL::Digest.new('SHA256')) - assert_equal(@rsa1024.public_to_der, req.public_key.public_to_der) + req = issue_csr(0, @dn, @rsa1, "SHA256") + assert_kind_of(OpenSSL::PKey::RSA, req.public_key) + assert_equal(@rsa1.public_to_der, req.public_key.public_to_der) req = OpenSSL::X509::Request.new(req.to_der) - assert_equal(@rsa1024.public_to_der, req.public_key.public_to_der) - - req = issue_csr(0, @dn, @dsa512, OpenSSL::Digest.new('SHA256')) - assert_equal(@dsa512.public_to_der, req.public_key.public_to_der) - req = OpenSSL::X509::Request.new(req.to_der) - assert_equal(@dsa512.public_to_der, req.public_key.public_to_der) + assert_equal(@rsa1.public_to_der, req.public_key.public_to_der) end def test_version - req = issue_csr(0, @dn, @rsa1024, OpenSSL::Digest.new('SHA256')) + req = issue_csr(0, @dn, @rsa1, "SHA256") assert_equal(0, req.version) req = OpenSSL::X509::Request.new(req.to_der) assert_equal(0, req.version) end def test_subject - req = issue_csr(0, @dn, @rsa1024, OpenSSL::Digest.new('SHA256')) + req = issue_csr(0, @dn, @rsa1, "SHA256") assert_equal(@dn.to_der, req.subject.to_der) req = OpenSSL::X509::Request.new(req.to_der) assert_equal(@dn.to_der, req.subject.to_der) end + def test_signature_algorithm + req = issue_csr(0, @dn, @rsa1, "SHA256") + assert_equal("sha256WithRSAEncryption", req.signature_algorithm) # ln + end + def create_ext_req(exts) ef = OpenSSL::X509::ExtensionFactory.new exts = exts.collect{|e| ef.create_extension(*e) } @@ -73,9 +72,9 @@ class OpenSSL::TestX509Request < OpenSSL::TestCase OpenSSL::X509::Attribute.new("msExtReq", attrval), ] - req0 = issue_csr(0, @dn, @rsa1024, OpenSSL::Digest.new('SHA256')) + req0 = issue_csr(0, @dn, @rsa1, "SHA256") attrs.each{|attr| req0.add_attribute(attr) } - req1 = issue_csr(0, @dn, @rsa1024, OpenSSL::Digest.new('SHA256')) + req1 = issue_csr(0, @dn, @rsa1, "SHA256") req1.attributes = attrs assert_equal(req0.to_der, req1.to_der) @@ -95,65 +94,44 @@ class OpenSSL::TestX509Request < OpenSSL::TestCase assert_equal(exts, get_ext_req(attrs[1].value)) end - def test_sign_and_verify_rsa_sha1 - req = issue_csr(0, @dn, @rsa1024, OpenSSL::Digest.new('SHA1')) - assert_equal(true, req.verify(@rsa1024)) - assert_equal(false, req.verify(@rsa2048)) - assert_equal(false, request_error_returns_false { req.verify(@dsa256) }) - assert_equal(false, request_error_returns_false { req.verify(@dsa512) }) - req.subject = OpenSSL::X509::Name.parse("/C=JP/CN=FooBarFooBar") - assert_equal(false, req.verify(@rsa1024)) - rescue OpenSSL::X509::RequestError # RHEL 9 disables SHA1 - end - - def test_sign_and_verify_rsa_md5 - req = issue_csr(0, @dn, @rsa2048, OpenSSL::Digest.new('MD5')) - assert_equal(false, req.verify(@rsa1024)) - assert_equal(true, req.verify(@rsa2048)) - assert_equal(false, request_error_returns_false { req.verify(@dsa256) }) - assert_equal(false, request_error_returns_false { req.verify(@dsa512) }) - req.subject = OpenSSL::X509::Name.parse("/C=JP/CN=FooBar") - assert_equal(false, req.verify(@rsa2048)) - rescue OpenSSL::X509::RequestError # RHEL7 disables MD5 - end - - def test_sign_and_verify_dsa - req = issue_csr(0, @dn, @dsa512, OpenSSL::Digest.new('SHA256')) - assert_equal(false, request_error_returns_false { req.verify(@rsa1024) }) - assert_equal(false, request_error_returns_false { req.verify(@rsa2048) }) - assert_equal(false, req.verify(@dsa256)) - assert_equal(true, req.verify(@dsa512)) - req.public_key = @rsa1024.public_key - assert_equal(false, req.verify(@dsa512)) + def test_sign_digest_instance + req1 = issue_csr(0, @dn, @rsa1, "SHA256") + req2 = issue_csr(0, @dn, @rsa1, OpenSSL::Digest.new("SHA256")) + assert_equal(req1.to_der, req2.to_der) end - def test_sign_and_verify_dsa_md5 - assert_raise(OpenSSL::X509::RequestError){ - issue_csr(0, @dn, @dsa512, OpenSSL::Digest.new('MD5')) } + def test_sign_and_verify + req = issue_csr(0, @dn, @rsa1, "SHA256") + assert_equal(true, req.verify(@rsa1)) + assert_equal(false, req.verify(@rsa2)) + ec = OpenSSL::PKey::EC.generate("prime256v1") + assert_equal(false, request_error_returns_false { req.verify(ec) }) + req.subject = OpenSSL::X509::Name.parse_rfc2253("CN=FooBarFooBar,C=JP") + assert_equal(false, req.verify(@rsa1)) end - def test_sign_and_verify_ed25519 + def test_sign_and_verify_nil_digest # Ed25519 is not FIPS-approved. omit_on_fips ed25519 = OpenSSL::PKey::generate_key("ED25519") req = issue_csr(0, @dn, ed25519, nil) - assert_equal(false, request_error_returns_false { req.verify(@rsa1024) }) - assert_equal(false, request_error_returns_false { req.verify(@rsa2048) }) + assert_equal(false, request_error_returns_false { req.verify(@rsa1) }) + assert_equal(false, request_error_returns_false { req.verify(@rsa2) }) assert_equal(false, req.verify(OpenSSL::PKey::generate_key("ED25519"))) assert_equal(true, req.verify(ed25519)) - req.public_key = @rsa1024.public_key + req.public_key = @rsa1 assert_equal(false, req.verify(ed25519)) end def test_dup - req = issue_csr(0, @dn, @rsa1024, OpenSSL::Digest.new('SHA256')) + req = issue_csr(0, @dn, @rsa1, "SHA256") assert_equal(req.to_der, req.dup.to_der) end def test_eq - req1 = issue_csr(0, @dn, @rsa1024, "sha256") - req2 = issue_csr(0, @dn, @rsa1024, "sha256") - req3 = issue_csr(0, @dn, @rsa1024, "sha512") + req1 = issue_csr(0, @dn, @rsa1, "SHA256") + req2 = issue_csr(0, @dn, @rsa1, "SHA256") + req3 = issue_csr(0, @dn, @rsa1, "SHA512") assert_equal false, req1 == 12345 assert_equal true, req1 == req2 @@ -161,7 +139,7 @@ class OpenSSL::TestX509Request < OpenSSL::TestCase end def test_marshal - req = issue_csr(0, @dn, @rsa1024, "sha256") + req = issue_csr(0, @dn, @rsa1, "SHA256") deserialized = Marshal.load(Marshal.dump(req)) assert_equal req.to_der, deserialized.to_der diff --git a/test/openssl/test_x509store.rb b/test/openssl/test_x509store.rb index 745ae7dd13..c13beae364 100644 --- a/test/openssl/test_x509store.rb +++ b/test/openssl/test_x509store.rb @@ -91,6 +91,18 @@ class OpenSSL::TestX509Store < OpenSSL::TestCase assert_match(/ok/i, store.error_string) assert_equal(OpenSSL::X509::V_OK, store.error) assert_equal([ee1_cert, ca2_cert, ca1_cert], store.chain) + + # Manually instantiated StoreContext + # Nothing trusted + store = OpenSSL::X509::Store.new + ctx = OpenSSL::X509::StoreContext.new(store, ee1_cert) + assert_nil(ctx.current_cert) + assert_nil(ctx.current_crl) + assert_equal(false, ctx.verify) + assert_equal(OpenSSL::X509::V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY, ctx.error) + assert_equal(0, ctx.error_depth) + assert_equal([ee1_cert], ctx.chain) + assert_equal(ee1_cert, ctx.current_cert) end def test_verify_callback diff --git a/test/openssl/utils.rb b/test/openssl/utils.rb index ff789ff284..7e6fe8b163 100644 --- a/test/openssl/utils.rb +++ b/test/openssl/utils.rb @@ -177,16 +177,16 @@ class OpenSSL::SSLTestCase < OpenSSL::TestCase @ca = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=CA") @svr = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=localhost") @cli = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=localhost") - ca_exts = [ + @ca_exts = [ ["basicConstraints","CA:TRUE",true], ["keyUsage","cRLSign,keyCertSign",true], ] - ee_exts = [ + @ee_exts = [ ["keyUsage","keyEncipherment,digitalSignature",true], ] - @ca_cert = issue_cert(@ca, @ca_key, 1, ca_exts, nil, nil) - @svr_cert = issue_cert(@svr, @svr_key, 2, ee_exts, @ca_cert, @ca_key) - @cli_cert = issue_cert(@cli, @cli_key, 3, ee_exts, @ca_cert, @ca_key) + @ca_cert = issue_cert(@ca, @ca_key, 1, @ca_exts, nil, nil) + @svr_cert = issue_cert(@svr, @svr_key, 2, @ee_exts, @ca_cert, @ca_key) + @cli_cert = issue_cert(@cli, @cli_key, 3, @ee_exts, @ca_cert, @ca_key) @server = nil end @@ -294,6 +294,33 @@ class OpenSSL::PKeyTestCase < OpenSSL::TestCase else assert_equal(false, ret) end + + def der_to_pem(der, pem_header) + # RFC 7468 + <<~EOS + -----BEGIN #{pem_header}----- + #{[der].pack("m0").scan(/.{1,64}/).join("\n")} + -----END #{pem_header}----- + EOS + end + + def der_to_encrypted_pem(der, pem_header, password) + # OpenSSL encryption, non-standard + iv = 16.times.to_a.pack("C*") + encrypted = OpenSSL::Cipher.new("aes-128-cbc").encrypt.then { |cipher| + cipher.key = OpenSSL::Digest.digest("MD5", password + iv[0, 8]) + cipher.iv = iv + cipher.update(der) << cipher.final + } + <<~EOS + -----BEGIN #{pem_header}----- + Proc-Type: 4,ENCRYPTED + DEK-Info: AES-128-CBC,#{iv.unpack1("H*").upcase} + + #{[encrypted].pack("m0").scan(/.{1,64}/).join("\n")} + -----END #{pem_header}----- + EOS + end end module OpenSSL::Certs |
