Skip to content

Commit 450721c

Browse files
committed
Fix test_kdf.rb in FIPS.
* 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) https://github.com/openssl/openssl/blob/71943544885ff364a10bcc5ffc62d0e651c9a021/providers/implementations/kdfs/pbkdf2.c#L235-L240 * 5.2 The Iteration Count (C) https://github.com/openssl/openssl/blob/71943544885ff364a10bcc5ffc62d0e651c9a021/providers/implementations/kdfs/pbkdf2.c#L247-L252 * scrypt (RFC 7914) 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 * Keep only one RFC 6070 test (test_pbkdf2_hmac_sha1_rfc6070_c_4096_len_25). Remove other RFC 6070 tests (test_*_rfc6070_*) don't work in FIPS. Keeping one RFC 6070 test is good enough. * Remove test_hkdf_rfc5869_test_case_4 in favor of the new test_hkdf_rfc5869_test_case_5. * We want to avoid conditional tests that don't work in FIPS as much as possible.
1 parent b61ff5a commit 450721c

2 files changed

Lines changed: 58 additions & 78 deletions

File tree

Rakefile

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@ Rake::TestTask.new(:test_fips_internal) do |t|
2626
# Exclude failing test files in FIPS for this task to pass.
2727
# TODO: Fix failing test files.
2828
t.test_files = FileList['test/**/test_*.rb'] - FileList[
29-
'test/openssl/test_kdf.rb',
3029
'test/openssl/test_ts.rb',
3130
]
3231
t.warning = true

test/openssl/test_kdf.rb

Lines changed: 58 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -5,64 +5,31 @@
55

66
class OpenSSL::TestKDF < OpenSSL::TestCase
77
def test_pkcs5_pbkdf2_hmac_compatibility
8-
expected = OpenSSL::KDF.pbkdf2_hmac("password", salt: "salt", iterations: 1, length: 20, hash: "sha1")
9-
assert_equal(expected, OpenSSL::PKCS5.pbkdf2_hmac("password", "salt", 1, 20, "sha1"))
10-
assert_equal(expected, OpenSSL::PKCS5.pbkdf2_hmac_sha1("password", "salt", 1, 20))
8+
# PBKDF2 salt >= 16 bytes (128 bits) and iterations >= 1000 are required in
9+
# FIPS.
10+
# SP 800-132.
11+
# https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-132.pdf
12+
# * 5.1 The Salt (S)
13+
# * 5.2 The Iteration Count (C)
14+
# https://github.com/openssl/openssl/blob/71943544885ff364a10bcc5ffc62d0e651c9a021/providers/implementations/kdfs/pbkdf2.c#L235-L240
15+
# https://github.com/openssl/openssl/blob/71943544885ff364a10bcc5ffc62d0e651c9a021/providers/implementations/kdfs/pbkdf2.c#L247-L252
16+
# Use the same parameters with test_pbkdf2_hmac_sha1_rfc6070_c_4096_len_25.
17+
expected = OpenSSL::KDF.pbkdf2_hmac("passwordPASSWORDpassword",
18+
salt: "saltSALTsaltSALTsaltSALTsaltSALTsalt",
19+
iterations: 4096,
20+
length: 25,
21+
hash: "sha1")
22+
assert_equal(expected, OpenSSL::PKCS5.pbkdf2_hmac("passwordPASSWORDpassword",
23+
"saltSALTsaltSALTsaltSALTsaltSALTsalt",
24+
4096,
25+
25,
26+
"sha1"))
27+
assert_equal(expected, OpenSSL::PKCS5.pbkdf2_hmac_sha1("passwordPASSWORDpassword",
28+
"saltSALTsaltSALTsaltSALTsaltSALTsalt",
29+
4096,
30+
25))
1131
end
1232

13-
def test_pbkdf2_hmac_sha1_rfc6070_c_1_len_20
14-
p ="password"
15-
s = "salt"
16-
c = 1
17-
dk_len = 20
18-
raw = %w{ 0c 60 c8 0f 96 1f 0e 71
19-
f3 a9 b5 24 af 60 12 06
20-
2f e0 37 a6 }
21-
expected = [raw.join('')].pack('H*')
22-
value = OpenSSL::KDF.pbkdf2_hmac(p, salt: s, iterations: c, length: dk_len, hash: "sha1")
23-
assert_equal(expected, value)
24-
end
25-
26-
def test_pbkdf2_hmac_sha1_rfc6070_c_2_len_20
27-
p ="password"
28-
s = "salt"
29-
c = 2
30-
dk_len = 20
31-
raw = %w{ ea 6c 01 4d c7 2d 6f 8c
32-
cd 1e d9 2a ce 1d 41 f0
33-
d8 de 89 57 }
34-
expected = [raw.join('')].pack('H*')
35-
value = OpenSSL::KDF.pbkdf2_hmac(p, salt: s, iterations: c, length: dk_len, hash: "sha1")
36-
assert_equal(expected, value)
37-
end
38-
39-
def test_pbkdf2_hmac_sha1_rfc6070_c_4096_len_20
40-
p ="password"
41-
s = "salt"
42-
c = 4096
43-
dk_len = 20
44-
raw = %w{ 4b 00 79 01 b7 65 48 9a
45-
be ad 49 d9 26 f7 21 d0
46-
65 a4 29 c1 }
47-
expected = [raw.join('')].pack('H*')
48-
value = OpenSSL::KDF.pbkdf2_hmac(p, salt: s, iterations: c, length: dk_len, hash: "sha1")
49-
assert_equal(expected, value)
50-
end
51-
52-
# takes too long!
53-
# def test_pbkdf2_hmac_sha1_rfc6070_c_16777216_len_20
54-
# p ="password"
55-
# s = "salt"
56-
# c = 16777216
57-
# dk_len = 20
58-
# raw = %w{ ee fe 3d 61 cd 4d a4 e4
59-
# e9 94 5b 3d 6b a2 15 8c
60-
# 26 34 e9 84 }
61-
# expected = [raw.join('')].pack('H*')
62-
# value = OpenSSL::KDF.pbkdf2_hmac(p, salt: s, iterations: c, length: dk_len, hash: "sha1")
63-
# assert_equal(expected, value)
64-
# end
65-
6633
def test_pbkdf2_hmac_sha1_rfc6070_c_4096_len_25
6734
p ="passwordPASSWORDpassword"
6835
s = "saltSALTsaltSALTsaltSALTsaltSALTsalt"
@@ -78,18 +45,6 @@ def test_pbkdf2_hmac_sha1_rfc6070_c_4096_len_25
7845
assert_equal(expected, value)
7946
end
8047

81-
def test_pbkdf2_hmac_sha1_rfc6070_c_4096_len_16
82-
p ="pass\0word"
83-
s = "sa\0lt"
84-
c = 4096
85-
dk_len = 16
86-
raw = %w{ 56 fa 6a a7 55 48 09 9d
87-
cc 37 d7 f0 34 25 e0 c3 }
88-
expected = [raw.join('')].pack('H*')
89-
value = OpenSSL::KDF.pbkdf2_hmac(p, salt: s, iterations: c, length: dk_len, hash: "sha1")
90-
assert_equal(expected, value)
91-
end
92-
9348
def test_pbkdf2_hmac_sha256_c_20000_len_32
9449
#unfortunately no official test vectors available yet for SHA-2
9550
p ="password"
@@ -103,6 +58,11 @@ def test_pbkdf2_hmac_sha256_c_20000_len_32
10358

10459
def test_scrypt_rfc7914_first
10560
pend "scrypt is not implemented" unless OpenSSL::KDF.respond_to?(:scrypt) # OpenSSL >= 1.1.0
61+
# scrypt is not available in FIPS.
62+
# EVP_KDF_fetch(ctx, OSSL_KDF_NAME_SCRYPT, propq) returns NULL in FIPS.
63+
# https://github.com/openssl/openssl/blob/71943544885ff364a10bcc5ffc62d0e651c9a021/crypto/evp/pbe_scrypt.c#L67-L71
64+
omit_on_fips
65+
10666
pass = ""
10767
salt = ""
10868
n = 16
@@ -118,6 +78,9 @@ def test_scrypt_rfc7914_first
11878

11979
def test_scrypt_rfc7914_second
12080
pend "scrypt is not implemented" unless OpenSSL::KDF.respond_to?(:scrypt) # OpenSSL >= 1.1.0
81+
# scrypt is not available in FIPS.
82+
omit_on_fips
83+
12184
pass = "password"
12285
salt = "NaCl"
12386
n = 1024
@@ -131,6 +94,7 @@ def test_scrypt_rfc7914_second
13194
assert_equal(expected, OpenSSL::KDF.scrypt(pass, salt: salt, N: n, r: r, p: p, length: dklen))
13295
end
13396

97+
# https://www.rfc-editor.org/rfc/rfc5869#appendix-A.1
13498
def test_hkdf_rfc5869_test_case_1
13599
hash = "sha256"
136100
ikm = B("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b")
@@ -144,6 +108,7 @@ def test_hkdf_rfc5869_test_case_1
144108
assert_equal(okm, OpenSSL::KDF.hkdf(ikm, salt: salt, info: info, length: l, hash: hash))
145109
end
146110

111+
# https://www.rfc-editor.org/rfc/rfc5869#appendix-A.3
147112
def test_hkdf_rfc5869_test_case_3
148113
hash = "sha256"
149114
ikm = B("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b")
@@ -157,16 +122,32 @@ def test_hkdf_rfc5869_test_case_3
157122
assert_equal(okm, OpenSSL::KDF.hkdf(ikm, salt: salt, info: info, length: l, hash: hash))
158123
end
159124

160-
def test_hkdf_rfc5869_test_case_4
125+
# https://www.rfc-editor.org/rfc/rfc5869#appendix-A.5
126+
def test_hkdf_rfc5869_test_case_5
161127
hash = "sha1"
162-
ikm = B("0b0b0b0b0b0b0b0b0b0b0b")
163-
salt = B("000102030405060708090a0b0c")
164-
info = B("f0f1f2f3f4f5f6f7f8f9")
165-
l = 42
166-
167-
okm = B("085a01ea1b10f36933068b56efa5ad81" \
168-
"a4f14b822f5b091568a9cdd4f155fda2" \
169-
"c22e422478d305f3f896")
128+
ikm = B("000102030405060708090a0b0c0d0e0f" \
129+
"101112131415161718191a1b1c1d1e1f" \
130+
"202122232425262728292a2b2c2d2e2f" \
131+
"303132333435363738393a3b3c3d3e3f" \
132+
"404142434445464748494a4b4c4d4e4f")
133+
salt = B("606162636465666768696a6b6c6d6e6f" \
134+
"707172737475767778797a7b7c7d7e7f" \
135+
"808182838485868788898a8b8c8d8e8f" \
136+
"909192939495969798999a9b9c9d9e9f" \
137+
"a0a1a2a3a4a5a6a7a8a9aaabacadaeaf")
138+
info = B("b0b1b2b3b4b5b6b7b8b9babbbcbdbebf" \
139+
"c0c1c2c3c4c5c6c7c8c9cacbcccdcecf" \
140+
"d0d1d2d3d4d5d6d7d8d9dadbdcdddedf" \
141+
"e0e1e2e3e4e5e6e7e8e9eaebecedeeef" \
142+
"f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff")
143+
l = 82
144+
145+
okm = B("0bd770a74d1160f7c9f12cd5912a06eb" \
146+
"ff6adcae899d92191fe4305673ba2ffe" \
147+
"8fa3f1a4e5ad79f3f334b3b202b2173c" \
148+
"486ea37ce3d397ed034c7f9dfeb15c5e" \
149+
"927336d0441f4c4300e2cff0d0900b52" \
150+
"d3b4")
170151
assert_equal(okm, OpenSSL::KDF.hkdf(ikm, salt: salt, info: info, length: l, hash: hash))
171152
end
172153

0 commit comments

Comments
 (0)