-
Notifications
You must be signed in to change notification settings - Fork 17
/
Copy pathparams.go
174 lines (159 loc) · 4.85 KB
/
params.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
//go:build !cmd_go_bootstrap
package openssl
import "C"
import (
"runtime"
)
type bnParam struct {
value _BIGNUM_PTR
private bool
}
// paramBuilder is a helper for building OSSL_PARAMs.
// If an error occurs when adding a new parameter,
// subsequent calls to add parameters are ignored
// and build() will return the error.
type paramBuilder struct {
bld _OSSL_PARAM_BLD_PTR
pinner runtime.Pinner
bnToFree []bnParam
err error
}
// newParamBuilder creates a new paramBuilder.
func newParamBuilder() (*paramBuilder, error) {
bld := go_openssl_OSSL_PARAM_BLD_new()
if bld == nil {
return nil, newOpenSSLError("OSSL_PARAM_BLD_new")
}
pb := ¶mBuilder{
bld: bld,
bnToFree: make([]bnParam, 0, 8), // the maximum known number of BIGNUMs to free are 8 for RSA
}
runtime.SetFinalizer(pb, (*paramBuilder).finalize)
return pb, nil
}
// finalize frees the builder.
func (b *paramBuilder) finalize() {
if b.bld != nil {
b.pinner.Unpin()
for _, bn := range b.bnToFree {
if bn.private {
go_openssl_BN_clear_free(bn.value)
} else {
go_openssl_BN_free(bn.value)
}
}
go_openssl_OSSL_PARAM_BLD_free(b.bld)
b.bld = nil
}
}
// check is used internally to enforce invariants and should not be called by users of paramBuilder.
// Returns true if it's ok to add parameters to the builder or build it.
// Returns false if there has been an error while adding a parameter.
// Panics if the paramBuilder has been freed, e.g. if it has already been built.
func (b *paramBuilder) check() bool {
if b.err != nil {
return false
}
if b.bld == nil {
panic("openssl: paramBuilder has been freed")
}
return true
}
// build creates an OSSL_PARAM from the builder.
// The returned OSSL_PARAM must be freed with OSSL_PARAM_free.
// If an error occurred while adding parameters, the error is returned
// and the OSSL_PARAM is nil. Once build() is called, the builder is finalized
// and cannot be reused.
func (b *paramBuilder) build() (_OSSL_PARAM_PTR, error) {
defer b.finalize()
if !b.check() {
return nil, b.err
}
param := go_openssl_OSSL_PARAM_BLD_to_param(b.bld)
if param == nil {
return nil, newOpenSSLError("OSSL_PARAM_BLD_build")
}
return param, nil
}
// addUTF8String adds a NUL-terminated UTF-8 string to the builder.
// size should not include the terminating NUL byte. If size is zero, then it will be calculated.
func (b *paramBuilder) addUTF8String(name cString, value *byte, size int) {
if !b.check() {
return
}
// OSSL_PARAM_BLD_push_utf8_string calculates the size if it is zero.
if go_openssl_OSSL_PARAM_BLD_push_utf8_string(b.bld, name.ptr(), value, size) != 1 {
b.err = newOpenSSLError("OSSL_PARAM_BLD_push_utf8_string(" + name.str() + ")")
}
}
// addOctetString adds an octet string to the builder.
// The value is pinned and will be unpinned when the builder is freed.
func (b *paramBuilder) addOctetString(name cString, value []byte) {
if !b.check() {
return
}
if len(value) != 0 {
b.pinner.Pin(&value[0])
}
if go_openssl_OSSL_PARAM_BLD_push_octet_string(b.bld, name.ptr(), pbase(value), len(value)) != 1 {
b.err = newOpenSSLError("OSSL_PARAM_BLD_push_octet_string(" + name.str() + ")")
}
}
// addInt32 adds an int32 to the builder.
func (b *paramBuilder) addInt32(name cString, value int32) {
if !b.check() {
return
}
if go_openssl_OSSL_PARAM_BLD_push_int32(b.bld, name.ptr(), value) != 1 {
b.err = newOpenSSLError("OSSL_PARAM_BLD_push_int32(" + name.str() + ")")
}
}
// addBN adds a GO_BIGNUM_PTR to the builder.
func (b *paramBuilder) addBN(name cString, value _BIGNUM_PTR) {
if !b.check() {
return
}
if go_openssl_OSSL_PARAM_BLD_push_BN(b.bld, name.ptr(), value) != 1 {
b.err = newOpenSSLError("OSSL_PARAM_BLD_push_BN(" + name.str() + ")")
}
}
// addBin adds a byte slice to the builder.
// The slice is converted to a BIGNUM using BN_bin2bn and freed when the builder is finalized.
// If private is true, the BIGNUM will be cleared with BN_clear_free,
// otherwise it will be freed with BN_free.
func (b *paramBuilder) addBin(name cString, value []byte, private bool) {
if !b.check() {
return
}
if len(value) == 0 {
// Nothing to do.
return
}
bn := go_openssl_BN_bin2bn(base(value), int32(len(value)), nil)
if bn == nil {
b.err = newOpenSSLError("BN_bin2bn")
return
}
b.bnToFree = append(b.bnToFree, bnParam{bn, private})
b.addBN(name, bn)
}
// addBigInt adds a BigInt to the builder.
// The BigInt is converted using bigToBN to a BIGNUM that is freed when the builder is finalized.
// If private is true, the BIGNUM will be cleared with BN_clear_free,
// otherwise it will be freed with BN_free.
func (b *paramBuilder) addBigInt(name cString, value BigInt, private bool) {
if !b.check() {
return
}
if len(value) == 0 {
// Nothing to do.
return
}
bn := bigToBN(value)
if bn == nil {
b.err = newOpenSSLError("bigToBN")
return
}
b.bnToFree = append(b.bnToFree, bnParam{bn, private})
b.addBN(name, bn)
}