Skip to content

Commit 1ee02b5

Browse files
authored
Merge pull request #116 from golang-fips/tls1prgret
tls1prf: require callers to pass in the result buffer
2 parents a4761ff + 2731067 commit 1ee02b5

File tree

2 files changed

+29
-22
lines changed

2 files changed

+29
-22
lines changed

tls1prf.go

+25-19
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,10 @@ func SupportsTLS1PRF() bool {
1616
(vMajor >= 1 && vMinor >= 1)
1717
}
1818

19-
func TLS1PRF(secret, label, seed []byte, keyLen int, h func() hash.Hash) ([]byte, error) {
19+
// TLS1PRF implements the TLS 1.0/1.1 pseudo-random function if h is nil,
20+
// else it implements the TLS 1.2 pseudo-random function.
21+
// The pseudo-random number will be written to result and will be of length len(result).
22+
func TLS1PRF(result, secret, label, seed []byte, h func() hash.Hash) error {
2023
var md C.GO_EVP_MD_PTR
2124
if h == nil {
2225
// TLS 1.0/1.1 PRF doesn't allow to specify the hash function,
@@ -29,70 +32,73 @@ func TLS1PRF(secret, label, seed []byte, keyLen int, h func() hash.Hash) ([]byte
2932
md = hashToMD(h())
3033
}
3134
if md == nil {
32-
return nil, errors.New("unsupported hash function")
35+
return errors.New("unsupported hash function")
3336
}
3437

3538
ctx := C.go_openssl_EVP_PKEY_CTX_new_id(C.GO_EVP_PKEY_TLS1_PRF, nil)
3639
if ctx == nil {
37-
return nil, newOpenSSLError("EVP_PKEY_CTX_new_id")
40+
return newOpenSSLError("EVP_PKEY_CTX_new_id")
3841
}
3942
defer func() {
4043
C.go_openssl_EVP_PKEY_CTX_free(ctx)
4144
}()
4245

4346
if C.go_openssl_EVP_PKEY_derive_init(ctx) != 1 {
44-
return nil, newOpenSSLError("EVP_PKEY_derive_init")
47+
return newOpenSSLError("EVP_PKEY_derive_init")
4548
}
4649
switch vMajor {
4750
case 3:
4851
if C.go_openssl_EVP_PKEY_CTX_set_tls1_prf_md(ctx, md) != 1 {
49-
return nil, newOpenSSLError("EVP_PKEY_CTX_set_tls1_prf_md")
52+
return newOpenSSLError("EVP_PKEY_CTX_set_tls1_prf_md")
5053
}
5154
if C.go_openssl_EVP_PKEY_CTX_set1_tls1_prf_secret(ctx,
5255
base(secret), C.int(len(secret))) != 1 {
53-
return nil, newOpenSSLError("EVP_PKEY_CTX_set1_tls1_prf_secret")
56+
return newOpenSSLError("EVP_PKEY_CTX_set1_tls1_prf_secret")
5457
}
5558
if C.go_openssl_EVP_PKEY_CTX_add1_tls1_prf_seed(ctx,
5659
base(label), C.int(len(label))) != 1 {
57-
return nil, newOpenSSLError("EVP_PKEY_CTX_add1_tls1_prf_seed")
60+
return newOpenSSLError("EVP_PKEY_CTX_add1_tls1_prf_seed")
5861
}
5962
if C.go_openssl_EVP_PKEY_CTX_add1_tls1_prf_seed(ctx,
6063
base(seed), C.int(len(seed))) != 1 {
61-
return nil, newOpenSSLError("EVP_PKEY_CTX_add1_tls1_prf_seed")
64+
return newOpenSSLError("EVP_PKEY_CTX_add1_tls1_prf_seed")
6265
}
6366
case 1:
6467
if C.go_openssl_EVP_PKEY_CTX_ctrl(ctx, -1,
6568
C.GO1_EVP_PKEY_OP_DERIVE,
6669
C.GO_EVP_PKEY_CTRL_TLS_MD,
6770
0, unsafe.Pointer(md)) != 1 {
68-
return nil, newOpenSSLError("EVP_PKEY_CTX_set_tls1_prf_md")
71+
return newOpenSSLError("EVP_PKEY_CTX_set_tls1_prf_md")
6972
}
7073
if C.go_openssl_EVP_PKEY_CTX_ctrl(ctx, -1,
7174
C.GO1_EVP_PKEY_OP_DERIVE,
7275
C.GO_EVP_PKEY_CTRL_TLS_SECRET,
7376
C.int(len(secret)), unsafe.Pointer(base(secret))) != 1 {
74-
return nil, newOpenSSLError("EVP_PKEY_CTX_set1_tls1_prf_secret")
77+
return newOpenSSLError("EVP_PKEY_CTX_set1_tls1_prf_secret")
7578
}
7679
if C.go_openssl_EVP_PKEY_CTX_ctrl(ctx, -1,
7780
C.GO1_EVP_PKEY_OP_DERIVE,
7881
C.GO_EVP_PKEY_CTRL_TLS_SEED,
7982
C.int(len(label)), unsafe.Pointer(base(label))) != 1 {
80-
return nil, newOpenSSLError("EVP_PKEY_CTX_add1_tls1_prf_seed")
83+
return newOpenSSLError("EVP_PKEY_CTX_add1_tls1_prf_seed")
8184
}
8285
if C.go_openssl_EVP_PKEY_CTX_ctrl(ctx, -1,
8386
C.GO1_EVP_PKEY_OP_DERIVE,
8487
C.GO_EVP_PKEY_CTRL_TLS_SEED,
8588
C.int(len(seed)), unsafe.Pointer(base(seed))) != 1 {
86-
return nil, newOpenSSLError("EVP_PKEY_CTX_add1_tls1_prf_seed")
89+
return newOpenSSLError("EVP_PKEY_CTX_add1_tls1_prf_seed")
8790
}
8891
}
89-
outLen := C.size_t(keyLen)
90-
out := make([]byte, outLen)
91-
if C.go_openssl_EVP_PKEY_derive(ctx, base(out), &outLen) != 1 {
92-
return nil, newOpenSSLError("EVP_PKEY_derive")
92+
outLen := C.size_t(len(result))
93+
if C.go_openssl_EVP_PKEY_derive(ctx, base(result), &outLen) != 1 {
94+
return newOpenSSLError("EVP_PKEY_derive")
9395
}
94-
if outLen != C.size_t(keyLen) {
95-
return nil, errors.New("tls1-prf: entropy limit reached")
96+
// The Go standard library expects TLS1PRF to return the requested number of bytes,
97+
// fail if it doesn't. While there is no known situation where this will happen,
98+
// EVP_PKEY_derive handles multiple algorithms and there could be a subtle mismatch
99+
// after more code changes in the future.
100+
if outLen != C.size_t(len(result)) {
101+
return errors.New("tls1-prf: derived less bytes than requested")
96102
}
97-
return out[:outLen], nil
103+
return nil
98104
}

tls1prf_test.go

+4-3
Original file line numberDiff line numberDiff line change
@@ -155,12 +155,13 @@ func TestTLS1PRF(t *testing.T) {
155155
if !openssl.SupportsHash(tt.hash) {
156156
t.Skip("skipping: hash not supported")
157157
}
158-
out, err := openssl.TLS1PRF(tt.secret, tt.label, tt.seed, len(tt.out), cryptoToHash(tt.hash))
158+
result := make([]byte, len(tt.out))
159+
err := openssl.TLS1PRF(result, tt.secret, tt.label, tt.seed, cryptoToHash(tt.hash))
159160
if err != nil {
160161
t.Fatalf("error deriving TLS 1.2 PRF: %v.", err)
161162
}
162-
if !bytes.Equal(out, tt.out) {
163-
t.Errorf("incorrect key output: have %v, need %v.", out, tt.out)
163+
if !bytes.Equal(result, tt.out) {
164+
t.Errorf("incorrect key output: have %v, need %v.", result, tt.out)
164165
}
165166
})
166167
}

0 commit comments

Comments
 (0)