@@ -60,6 +60,122 @@ def test_s_generate_key
6060 assert_not_equal nil , pkey . private_key
6161 end
6262
63+ def test_s_read_pem_unknown_block
64+ # A PEM-encoded certificate and a PEM-encoded private key are combined.
65+ # Check that OSSL_STORE doesn't stop after the first PEM block.
66+ orig = Fixtures . pkey ( "rsa-1" )
67+ subject = OpenSSL ::X509 ::Name . new ( [ [ "CN" , "test" ] ] )
68+ cert = issue_cert ( subject , orig , 1 , [ ] , nil , nil )
69+
70+ input = cert . to_text + cert . to_pem + orig . to_text + orig . private_to_pem
71+ pkey = OpenSSL ::PKey . read ( input )
72+ assert_equal ( orig . private_to_der , pkey . private_to_der )
73+ end
74+
75+ def test_s_read_der_then_pem
76+ # If the input is valid as both DER and PEM (which allows garbage data
77+ # before and after the block), it is read as DER
78+ #
79+ # TODO: Garbage data after DER should not be allowed, but it is currently
80+ # ignored
81+ orig1 = Fixtures . pkey ( "rsa-1" )
82+ orig2 = Fixtures . pkey ( "rsa-2" )
83+ pkey = OpenSSL ::PKey . read ( orig1 . public_to_der + orig2 . private_to_pem )
84+ assert_equal ( orig1 . public_to_der , pkey . public_to_der )
85+ assert_not_predicate ( pkey , :private? )
86+ end
87+
88+ def test_s_read_passphrase
89+ orig = Fixtures . pkey ( "rsa-1" )
90+ encrypted_pem = orig . private_to_pem ( "AES-256-CBC" , "correct_passphrase" )
91+ assert_match ( /\A -----BEGIN ENCRYPTED PRIVATE KEY-----/ , encrypted_pem )
92+
93+ # Correct passphrase passed as the second argument
94+ pkey1 = OpenSSL ::PKey . read ( encrypted_pem , "correct_passphrase" )
95+ assert_equal ( orig . private_to_der , pkey1 . private_to_der )
96+
97+ # Correct passphrase returned by the block. The block gets false
98+ called = 0
99+ flag = nil
100+ pkey2 = OpenSSL ::PKey . read ( encrypted_pem ) { |f |
101+ called += 1
102+ flag = f
103+ "correct_passphrase"
104+ }
105+ assert_equal ( orig . private_to_der , pkey2 . private_to_der )
106+ assert_equal ( 1 , called )
107+ assert_false ( flag )
108+
109+ # Incorrect passphrase passed. The block is not called
110+ called = 0
111+ assert_raise ( OpenSSL ::PKey ::PKeyError ) {
112+ OpenSSL ::PKey . read ( encrypted_pem , "incorrect_passphrase" ) {
113+ called += 1
114+ }
115+ }
116+ assert_equal ( 0 , called )
117+
118+ # Incorrect passphrase returned by the block. The block is called only once
119+ called = 0
120+ assert_raise ( OpenSSL ::PKey ::PKeyError ) {
121+ OpenSSL ::PKey . read ( encrypted_pem ) {
122+ called += 1
123+ "incorrect_passphrase"
124+ }
125+ }
126+ assert_equal ( 1 , called )
127+
128+ # Incorrect passphrase returned by the block. The input contains two PEM
129+ # blocks.
130+ called = 0
131+ assert_raise ( OpenSSL ::PKey ::PKeyError ) {
132+ OpenSSL ::PKey . read ( encrypted_pem + encrypted_pem ) {
133+ called += 1
134+ "incorrect_passphrase"
135+ }
136+ }
137+ assert_equal ( 1 , called )
138+ end
139+
140+ def test_s_read_passphrase_tty
141+ omit "https://github.com/aws/aws-lc/pull/2555" if aws_lc?
142+
143+ orig = Fixtures . pkey ( "rsa-1" )
144+ encrypted_pem = orig . private_to_pem ( "AES-256-CBC" , "correct_passphrase" )
145+
146+ # Correct passphrase passed to OpenSSL's prompt
147+ script = <<~"end;"
148+ require "openssl"
149+ Process.setsid
150+ OpenSSL::PKey.read(#{ encrypted_pem . dump } )
151+ puts "ok"
152+ end;
153+ assert_in_out_err ( [ *$:. map { |l | "-I#{ l } " } , "-e#{ script } " ] ,
154+ "correct_passphrase\n " ) { |stdout , stderr |
155+ assert_equal ( [ "Enter PEM pass phrase:" ] , stderr )
156+ assert_equal ( [ "ok" ] , stdout )
157+ }
158+
159+ # Incorrect passphrase passed to OpenSSL's prompt
160+ script = <<~"end;"
161+ require "openssl"
162+ Process.setsid
163+ begin
164+ OpenSSL::PKey.read(#{ encrypted_pem . dump } )
165+ rescue OpenSSL::PKey::PKeyError
166+ puts "ok"
167+ else
168+ puts "expected OpenSSL::PKey::PKeyError"
169+ end
170+ end;
171+ stdin = "incorrect_passphrase\n " * 5
172+ assert_in_out_err ( [ *$:. map { |l | "-I#{ l } " } , "-e#{ script } " ] ,
173+ stdin ) { |stdout , stderr |
174+ assert_equal ( 1 , stderr . count ( "Enter PEM pass phrase:" ) )
175+ assert_equal ( [ "ok" ] , stdout )
176+ }
177+ end if ENV [ "OSSL_TEST_ALL" ] == "1" && Process . respond_to? ( :setsid )
178+
63179 def test_hmac_sign_verify
64180 pkey = OpenSSL ::PKey . generate_key ( "HMAC" , { "key" => "abcd" } )
65181
0 commit comments