@@ -8,12 +8,20 @@ import (
8
8
"crypto"
9
9
"errors"
10
10
"hash"
11
+ "sync"
11
12
"unsafe"
12
13
)
13
14
14
15
func SupportsTLS1PRF () bool {
15
- return vMajor > 1 ||
16
- (vMajor >= 1 && vMinor >= 1 )
16
+ switch vMajor {
17
+ case 1 :
18
+ return vMinor >= 1
19
+ case 3 :
20
+ _ , err := fetchTLS1PRF3 ()
21
+ return err == nil
22
+ default :
23
+ panic (errUnsupportedVersion ())
24
+ }
17
25
}
18
26
19
27
// TLS1PRF implements the TLS 1.0/1.1 pseudo-random function if h is nil,
@@ -39,6 +47,20 @@ func TLS1PRF(result, secret, label, seed []byte, fh func() hash.Hash) error {
39
47
return errors .New ("unsupported hash function" )
40
48
}
41
49
50
+ switch vMajor {
51
+ case 1 :
52
+ return tls1PRF1 (result , secret , label , seed , md )
53
+ case 3 :
54
+ return tls1PRF3 (result , secret , label , seed , md )
55
+ default :
56
+ return errUnsupportedVersion ()
57
+ }
58
+ }
59
+
60
+ // tls1PRF1 implements TLS1PRF for OpenSSL 1 using the EVP_PKEY API.
61
+ func tls1PRF1 (result , secret , label , seed []byte , md C.GO_EVP_MD_PTR ) error {
62
+ checkMajorVersion (1 )
63
+
42
64
ctx := C .go_openssl_EVP_PKEY_CTX_new_id (C .GO_EVP_PKEY_TLS1_PRF , nil )
43
65
if ctx == nil {
44
66
return newOpenSSLError ("EVP_PKEY_CTX_new_id" )
@@ -50,48 +72,29 @@ func TLS1PRF(result, secret, label, seed []byte, fh func() hash.Hash) error {
50
72
if C .go_openssl_EVP_PKEY_derive_init (ctx ) != 1 {
51
73
return newOpenSSLError ("EVP_PKEY_derive_init" )
52
74
}
53
- switch vMajor {
54
- case 3 :
55
- if C .go_openssl_EVP_PKEY_CTX_set_tls1_prf_md (ctx , md ) != 1 {
56
- return newOpenSSLError ("EVP_PKEY_CTX_set_tls1_prf_md" )
57
- }
58
- if C .go_openssl_EVP_PKEY_CTX_set1_tls1_prf_secret (ctx ,
59
- base (secret ), C .int (len (secret ))) != 1 {
60
- return newOpenSSLError ("EVP_PKEY_CTX_set1_tls1_prf_secret" )
61
- }
62
- if C .go_openssl_EVP_PKEY_CTX_add1_tls1_prf_seed (ctx ,
63
- base (label ), C .int (len (label ))) != 1 {
64
- return newOpenSSLError ("EVP_PKEY_CTX_add1_tls1_prf_seed" )
65
- }
66
- if C .go_openssl_EVP_PKEY_CTX_add1_tls1_prf_seed (ctx ,
67
- base (seed ), C .int (len (seed ))) != 1 {
68
- return newOpenSSLError ("EVP_PKEY_CTX_add1_tls1_prf_seed" )
69
- }
70
- case 1 :
71
- if C .go_openssl_EVP_PKEY_CTX_ctrl (ctx , - 1 ,
72
- C .GO1_EVP_PKEY_OP_DERIVE ,
73
- C .GO_EVP_PKEY_CTRL_TLS_MD ,
74
- 0 , unsafe .Pointer (md )) != 1 {
75
- return newOpenSSLError ("EVP_PKEY_CTX_set_tls1_prf_md" )
76
- }
77
- if C .go_openssl_EVP_PKEY_CTX_ctrl (ctx , - 1 ,
78
- C .GO1_EVP_PKEY_OP_DERIVE ,
79
- C .GO_EVP_PKEY_CTRL_TLS_SECRET ,
80
- C .int (len (secret )), unsafe .Pointer (base (secret ))) != 1 {
81
- return newOpenSSLError ("EVP_PKEY_CTX_set1_tls1_prf_secret" )
82
- }
83
- if C .go_openssl_EVP_PKEY_CTX_ctrl (ctx , - 1 ,
84
- C .GO1_EVP_PKEY_OP_DERIVE ,
85
- C .GO_EVP_PKEY_CTRL_TLS_SEED ,
86
- C .int (len (label )), unsafe .Pointer (base (label ))) != 1 {
87
- return newOpenSSLError ("EVP_PKEY_CTX_add1_tls1_prf_seed" )
88
- }
89
- if C .go_openssl_EVP_PKEY_CTX_ctrl (ctx , - 1 ,
90
- C .GO1_EVP_PKEY_OP_DERIVE ,
91
- C .GO_EVP_PKEY_CTRL_TLS_SEED ,
92
- C .int (len (seed )), unsafe .Pointer (base (seed ))) != 1 {
93
- return newOpenSSLError ("EVP_PKEY_CTX_add1_tls1_prf_seed" )
94
- }
75
+ if C .go_openssl_EVP_PKEY_CTX_ctrl (ctx , - 1 ,
76
+ C .GO1_EVP_PKEY_OP_DERIVE ,
77
+ C .GO_EVP_PKEY_CTRL_TLS_MD ,
78
+ 0 , unsafe .Pointer (md )) != 1 {
79
+ return newOpenSSLError ("EVP_PKEY_CTX_set_tls1_prf_md" )
80
+ }
81
+ if C .go_openssl_EVP_PKEY_CTX_ctrl (ctx , - 1 ,
82
+ C .GO1_EVP_PKEY_OP_DERIVE ,
83
+ C .GO_EVP_PKEY_CTRL_TLS_SECRET ,
84
+ C .int (len (secret )), unsafe .Pointer (base (secret ))) != 1 {
85
+ return newOpenSSLError ("EVP_PKEY_CTX_set1_tls1_prf_secret" )
86
+ }
87
+ if C .go_openssl_EVP_PKEY_CTX_ctrl (ctx , - 1 ,
88
+ C .GO1_EVP_PKEY_OP_DERIVE ,
89
+ C .GO_EVP_PKEY_CTRL_TLS_SEED ,
90
+ C .int (len (label )), unsafe .Pointer (base (label ))) != 1 {
91
+ return newOpenSSLError ("EVP_PKEY_CTX_add1_tls1_prf_seed" )
92
+ }
93
+ if C .go_openssl_EVP_PKEY_CTX_ctrl (ctx , - 1 ,
94
+ C .GO1_EVP_PKEY_OP_DERIVE ,
95
+ C .GO_EVP_PKEY_CTRL_TLS_SEED ,
96
+ C .int (len (seed )), unsafe .Pointer (base (seed ))) != 1 {
97
+ return newOpenSSLError ("EVP_PKEY_CTX_add1_tls1_prf_seed" )
95
98
}
96
99
outLen := C .size_t (len (result ))
97
100
if C .go_openssl_EVP_PKEY_derive_wrapper (ctx , base (result ), outLen ).result != 1 {
@@ -106,3 +109,52 @@ func TLS1PRF(result, secret, label, seed []byte, fh func() hash.Hash) error {
106
109
}
107
110
return nil
108
111
}
112
+
113
+ // fetchTLS1PRF3 fetches the TLS1-PRF KDF algorithm.
114
+ // It is safe to call this function concurrently.
115
+ // The returned EVP_KDF_PTR shouldn't be freed.
116
+ var fetchTLS1PRF3 = sync .OnceValues (func () (C.GO_EVP_KDF_PTR , error ) {
117
+ checkMajorVersion (3 )
118
+
119
+ name := C .CString ("TLS1-PRF" )
120
+ kdf := C .go_openssl_EVP_KDF_fetch (nil , name , nil )
121
+ C .free (unsafe .Pointer (name ))
122
+ if kdf == nil {
123
+ return nil , newOpenSSLError ("EVP_KDF_fetch" )
124
+ }
125
+ return kdf , nil
126
+ })
127
+
128
+ // tls1PRF3 implements TLS1PRF for OpenSSL 3 using the EVP_KDF API.
129
+ func tls1PRF3 (result , secret , label , seed []byte , md C.GO_EVP_MD_PTR ) error {
130
+ checkMajorVersion (3 )
131
+
132
+ kdf , err := fetchTLS1PRF3 ()
133
+ if err != nil {
134
+ return err
135
+ }
136
+ ctx := C .go_openssl_EVP_KDF_CTX_new (kdf )
137
+ if ctx == nil {
138
+ return newOpenSSLError ("EVP_KDF_CTX_new" )
139
+ }
140
+ defer C .go_openssl_EVP_KDF_CTX_free (ctx )
141
+
142
+ bld , err := newParamBuilder ()
143
+ if err != nil {
144
+ return err
145
+ }
146
+ bld .addUTF8String (_OSSL_KDF_PARAM_DIGEST , C .go_openssl_EVP_MD_get0_name (md ), 0 )
147
+ bld .addOctetString (_OSSL_KDF_PARAM_SECRET , secret )
148
+ bld .addOctetString (_OSSL_KDF_PARAM_SEED , label )
149
+ bld .addOctetString (_OSSL_KDF_PARAM_SEED , seed )
150
+ params , err := bld .build ()
151
+ if err != nil {
152
+ return err
153
+ }
154
+ defer C .go_openssl_OSSL_PARAM_free (params )
155
+
156
+ if C .go_openssl_EVP_KDF_derive (ctx , base (result ), C .size_t (len (result )), params ) != 1 {
157
+ return newOpenSSLError ("EVP_KDF_derive" )
158
+ }
159
+ return nil
160
+ }
0 commit comments