github.com/mtsmfm/go/src@v0.0.0-20221020090648-44bdcb9f8fde/crypto/internal/boring/rsa.go (about) 1 // Copyright 2017 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 //go:build boringcrypto && linux && (amd64 || arm64) && !android && !cmd_go_bootstrap && !msan 6 7 package boring 8 9 // #include "goboringcrypto.h" 10 import "C" 11 import ( 12 "crypto" 13 "crypto/subtle" 14 "errors" 15 "hash" 16 "runtime" 17 "strconv" 18 "unsafe" 19 ) 20 21 func GenerateKeyRSA(bits int) (N, E, D, P, Q, Dp, Dq, Qinv BigInt, err error) { 22 bad := func(e error) (N, E, D, P, Q, Dp, Dq, Qinv BigInt, err error) { 23 return nil, nil, nil, nil, nil, nil, nil, nil, e 24 } 25 26 key := C._goboringcrypto_RSA_new() 27 if key == nil { 28 return bad(fail("RSA_new")) 29 } 30 defer C._goboringcrypto_RSA_free(key) 31 32 if C._goboringcrypto_RSA_generate_key_fips(key, C.int(bits), nil) == 0 { 33 return bad(fail("RSA_generate_key_fips")) 34 } 35 36 var n, e, d, p, q, dp, dq, qinv *C.GO_BIGNUM 37 C._goboringcrypto_RSA_get0_key(key, &n, &e, &d) 38 C._goboringcrypto_RSA_get0_factors(key, &p, &q) 39 C._goboringcrypto_RSA_get0_crt_params(key, &dp, &dq, &qinv) 40 return bnToBig(n), bnToBig(e), bnToBig(d), bnToBig(p), bnToBig(q), bnToBig(dp), bnToBig(dq), bnToBig(qinv), nil 41 } 42 43 type PublicKeyRSA struct { 44 // _key MUST NOT be accessed directly. Instead, use the withKey method. 45 _key *C.GO_RSA 46 } 47 48 func NewPublicKeyRSA(N, E BigInt) (*PublicKeyRSA, error) { 49 key := C._goboringcrypto_RSA_new() 50 if key == nil { 51 return nil, fail("RSA_new") 52 } 53 if !bigToBn(&key.n, N) || 54 !bigToBn(&key.e, E) { 55 return nil, fail("BN_bin2bn") 56 } 57 k := &PublicKeyRSA{_key: key} 58 runtime.SetFinalizer(k, (*PublicKeyRSA).finalize) 59 return k, nil 60 } 61 62 func (k *PublicKeyRSA) finalize() { 63 C._goboringcrypto_RSA_free(k._key) 64 } 65 66 func (k *PublicKeyRSA) withKey(f func(*C.GO_RSA) C.int) C.int { 67 // Because of the finalizer, any time _key is passed to cgo, that call must 68 // be followed by a call to runtime.KeepAlive, to make sure k is not 69 // collected (and finalized) before the cgo call returns. 70 defer runtime.KeepAlive(k) 71 return f(k._key) 72 } 73 74 type PrivateKeyRSA struct { 75 // _key MUST NOT be accessed directly. Instead, use the withKey method. 76 _key *C.GO_RSA 77 } 78 79 func NewPrivateKeyRSA(N, E, D, P, Q, Dp, Dq, Qinv BigInt) (*PrivateKeyRSA, error) { 80 key := C._goboringcrypto_RSA_new() 81 if key == nil { 82 return nil, fail("RSA_new") 83 } 84 if !bigToBn(&key.n, N) || 85 !bigToBn(&key.e, E) || 86 !bigToBn(&key.d, D) || 87 !bigToBn(&key.p, P) || 88 !bigToBn(&key.q, Q) || 89 !bigToBn(&key.dmp1, Dp) || 90 !bigToBn(&key.dmq1, Dq) || 91 !bigToBn(&key.iqmp, Qinv) { 92 return nil, fail("BN_bin2bn") 93 } 94 k := &PrivateKeyRSA{_key: key} 95 runtime.SetFinalizer(k, (*PrivateKeyRSA).finalize) 96 return k, nil 97 } 98 99 func (k *PrivateKeyRSA) finalize() { 100 C._goboringcrypto_RSA_free(k._key) 101 } 102 103 func (k *PrivateKeyRSA) withKey(f func(*C.GO_RSA) C.int) C.int { 104 // Because of the finalizer, any time _key is passed to cgo, that call must 105 // be followed by a call to runtime.KeepAlive, to make sure k is not 106 // collected (and finalized) before the cgo call returns. 107 defer runtime.KeepAlive(k) 108 return f(k._key) 109 } 110 111 func setupRSA(withKey func(func(*C.GO_RSA) C.int) C.int, 112 padding C.int, h hash.Hash, label []byte, saltLen int, ch crypto.Hash, 113 init func(*C.GO_EVP_PKEY_CTX) C.int) (pkey *C.GO_EVP_PKEY, ctx *C.GO_EVP_PKEY_CTX, err error) { 114 defer func() { 115 if err != nil { 116 if pkey != nil { 117 C._goboringcrypto_EVP_PKEY_free(pkey) 118 pkey = nil 119 } 120 if ctx != nil { 121 C._goboringcrypto_EVP_PKEY_CTX_free(ctx) 122 ctx = nil 123 } 124 } 125 }() 126 127 pkey = C._goboringcrypto_EVP_PKEY_new() 128 if pkey == nil { 129 return nil, nil, fail("EVP_PKEY_new") 130 } 131 if withKey(func(key *C.GO_RSA) C.int { 132 return C._goboringcrypto_EVP_PKEY_set1_RSA(pkey, key) 133 }) == 0 { 134 return nil, nil, fail("EVP_PKEY_set1_RSA") 135 } 136 ctx = C._goboringcrypto_EVP_PKEY_CTX_new(pkey, nil) 137 if ctx == nil { 138 return nil, nil, fail("EVP_PKEY_CTX_new") 139 } 140 if init(ctx) == 0 { 141 return nil, nil, fail("EVP_PKEY_operation_init") 142 } 143 if C._goboringcrypto_EVP_PKEY_CTX_set_rsa_padding(ctx, padding) == 0 { 144 return nil, nil, fail("EVP_PKEY_CTX_set_rsa_padding") 145 } 146 if padding == C.GO_RSA_PKCS1_OAEP_PADDING { 147 md := hashToMD(h) 148 if md == nil { 149 return nil, nil, errors.New("crypto/rsa: unsupported hash function") 150 } 151 if C._goboringcrypto_EVP_PKEY_CTX_set_rsa_oaep_md(ctx, md) == 0 { 152 return nil, nil, fail("EVP_PKEY_set_rsa_oaep_md") 153 } 154 // ctx takes ownership of label, so malloc a copy for BoringCrypto to free. 155 clabel := (*C.uint8_t)(C._goboringcrypto_OPENSSL_malloc(C.size_t(len(label)))) 156 if clabel == nil { 157 return nil, nil, fail("OPENSSL_malloc") 158 } 159 copy((*[1 << 30]byte)(unsafe.Pointer(clabel))[:len(label)], label) 160 if C._goboringcrypto_EVP_PKEY_CTX_set0_rsa_oaep_label(ctx, clabel, C.size_t(len(label))) == 0 { 161 return nil, nil, fail("EVP_PKEY_CTX_set0_rsa_oaep_label") 162 } 163 } 164 if padding == C.GO_RSA_PKCS1_PSS_PADDING { 165 if saltLen != 0 { 166 if C._goboringcrypto_EVP_PKEY_CTX_set_rsa_pss_saltlen(ctx, C.int(saltLen)) == 0 { 167 return nil, nil, fail("EVP_PKEY_set_rsa_pss_saltlen") 168 } 169 } 170 md := cryptoHashToMD(ch) 171 if md == nil { 172 return nil, nil, errors.New("crypto/rsa: unsupported hash function") 173 } 174 if C._goboringcrypto_EVP_PKEY_CTX_set_rsa_mgf1_md(ctx, md) == 0 { 175 return nil, nil, fail("EVP_PKEY_set_rsa_mgf1_md") 176 } 177 } 178 179 return pkey, ctx, nil 180 } 181 182 func cryptRSA(withKey func(func(*C.GO_RSA) C.int) C.int, 183 padding C.int, h hash.Hash, label []byte, saltLen int, ch crypto.Hash, 184 init func(*C.GO_EVP_PKEY_CTX) C.int, 185 crypt func(*C.GO_EVP_PKEY_CTX, *C.uint8_t, *C.size_t, *C.uint8_t, C.size_t) C.int, 186 in []byte) ([]byte, error) { 187 188 pkey, ctx, err := setupRSA(withKey, padding, h, label, saltLen, ch, init) 189 if err != nil { 190 return nil, err 191 } 192 defer C._goboringcrypto_EVP_PKEY_free(pkey) 193 defer C._goboringcrypto_EVP_PKEY_CTX_free(ctx) 194 195 var outLen C.size_t 196 if crypt(ctx, nil, &outLen, base(in), C.size_t(len(in))) == 0 { 197 return nil, fail("EVP_PKEY_decrypt/encrypt") 198 } 199 out := make([]byte, outLen) 200 if crypt(ctx, base(out), &outLen, base(in), C.size_t(len(in))) == 0 { 201 return nil, fail("EVP_PKEY_decrypt/encrypt") 202 } 203 return out[:outLen], nil 204 } 205 206 func DecryptRSAOAEP(h hash.Hash, priv *PrivateKeyRSA, ciphertext, label []byte) ([]byte, error) { 207 return cryptRSA(priv.withKey, C.GO_RSA_PKCS1_OAEP_PADDING, h, label, 0, 0, decryptInit, decrypt, ciphertext) 208 } 209 210 func EncryptRSAOAEP(h hash.Hash, pub *PublicKeyRSA, msg, label []byte) ([]byte, error) { 211 return cryptRSA(pub.withKey, C.GO_RSA_PKCS1_OAEP_PADDING, h, label, 0, 0, encryptInit, encrypt, msg) 212 } 213 214 func DecryptRSAPKCS1(priv *PrivateKeyRSA, ciphertext []byte) ([]byte, error) { 215 return cryptRSA(priv.withKey, C.GO_RSA_PKCS1_PADDING, nil, nil, 0, 0, decryptInit, decrypt, ciphertext) 216 } 217 218 func EncryptRSAPKCS1(pub *PublicKeyRSA, msg []byte) ([]byte, error) { 219 return cryptRSA(pub.withKey, C.GO_RSA_PKCS1_PADDING, nil, nil, 0, 0, encryptInit, encrypt, msg) 220 } 221 222 func DecryptRSANoPadding(priv *PrivateKeyRSA, ciphertext []byte) ([]byte, error) { 223 return cryptRSA(priv.withKey, C.GO_RSA_NO_PADDING, nil, nil, 0, 0, decryptInit, decrypt, ciphertext) 224 } 225 226 func EncryptRSANoPadding(pub *PublicKeyRSA, msg []byte) ([]byte, error) { 227 return cryptRSA(pub.withKey, C.GO_RSA_NO_PADDING, nil, nil, 0, 0, encryptInit, encrypt, msg) 228 } 229 230 // These dumb wrappers work around the fact that cgo functions cannot be used as values directly. 231 232 func decryptInit(ctx *C.GO_EVP_PKEY_CTX) C.int { 233 return C._goboringcrypto_EVP_PKEY_decrypt_init(ctx) 234 } 235 236 func decrypt(ctx *C.GO_EVP_PKEY_CTX, out *C.uint8_t, outLen *C.size_t, in *C.uint8_t, inLen C.size_t) C.int { 237 return C._goboringcrypto_EVP_PKEY_decrypt(ctx, out, outLen, in, inLen) 238 } 239 240 func encryptInit(ctx *C.GO_EVP_PKEY_CTX) C.int { 241 return C._goboringcrypto_EVP_PKEY_encrypt_init(ctx) 242 } 243 244 func encrypt(ctx *C.GO_EVP_PKEY_CTX, out *C.uint8_t, outLen *C.size_t, in *C.uint8_t, inLen C.size_t) C.int { 245 return C._goboringcrypto_EVP_PKEY_encrypt(ctx, out, outLen, in, inLen) 246 } 247 248 var invalidSaltLenErr = errors.New("crypto/rsa: PSSOptions.SaltLength cannot be negative") 249 250 func SignRSAPSS(priv *PrivateKeyRSA, h crypto.Hash, hashed []byte, saltLen int) ([]byte, error) { 251 md := cryptoHashToMD(h) 252 if md == nil { 253 return nil, errors.New("crypto/rsa: unsupported hash function") 254 } 255 256 // A salt length of -2 is valid in BoringSSL, but not in crypto/rsa, so reject 257 // it, and lengths < -2, before we convert to the BoringSSL sentinel values. 258 if saltLen <= -2 { 259 return nil, invalidSaltLenErr 260 } 261 262 // BoringSSL uses sentinel salt length values like we do, but the values don't 263 // fully match what we use. We both use -1 for salt length equal to hash length, 264 // but BoringSSL uses -2 to mean maximal size where we use 0. In the latter 265 // case convert to the BoringSSL version. 266 if saltLen == 0 { 267 saltLen = -2 268 } 269 270 var out []byte 271 var outLen C.size_t 272 if priv.withKey(func(key *C.GO_RSA) C.int { 273 out = make([]byte, C._goboringcrypto_RSA_size(key)) 274 return C._goboringcrypto_RSA_sign_pss_mgf1(key, &outLen, base(out), C.size_t(len(out)), 275 base(hashed), C.size_t(len(hashed)), md, nil, C.int(saltLen)) 276 }) == 0 { 277 return nil, fail("RSA_sign_pss_mgf1") 278 } 279 280 return out[:outLen], nil 281 } 282 283 func VerifyRSAPSS(pub *PublicKeyRSA, h crypto.Hash, hashed, sig []byte, saltLen int) error { 284 md := cryptoHashToMD(h) 285 if md == nil { 286 return errors.New("crypto/rsa: unsupported hash function") 287 } 288 289 // A salt length of -2 is valid in BoringSSL, but not in crypto/rsa, so reject 290 // it, and lengths < -2, before we convert to the BoringSSL sentinel values. 291 if saltLen <= -2 { 292 return invalidSaltLenErr 293 } 294 295 // BoringSSL uses sentinel salt length values like we do, but the values don't 296 // fully match what we use. We both use -1 for salt length equal to hash length, 297 // but BoringSSL uses -2 to mean maximal size where we use 0. In the latter 298 // case convert to the BoringSSL version. 299 if saltLen == 0 { 300 saltLen = -2 301 } 302 303 if pub.withKey(func(key *C.GO_RSA) C.int { 304 return C._goboringcrypto_RSA_verify_pss_mgf1(key, base(hashed), C.size_t(len(hashed)), 305 md, nil, C.int(saltLen), base(sig), C.size_t(len(sig))) 306 }) == 0 { 307 return fail("RSA_verify_pss_mgf1") 308 } 309 return nil 310 } 311 312 func SignRSAPKCS1v15(priv *PrivateKeyRSA, h crypto.Hash, hashed []byte) ([]byte, error) { 313 if h == 0 { 314 // No hashing. 315 var out []byte 316 var outLen C.size_t 317 if priv.withKey(func(key *C.GO_RSA) C.int { 318 out = make([]byte, C._goboringcrypto_RSA_size(key)) 319 return C._goboringcrypto_RSA_sign_raw(key, &outLen, base(out), C.size_t(len(out)), 320 base(hashed), C.size_t(len(hashed)), C.GO_RSA_PKCS1_PADDING) 321 }) == 0 { 322 return nil, fail("RSA_sign_raw") 323 } 324 return out[:outLen], nil 325 } 326 327 md := cryptoHashToMD(h) 328 if md == nil { 329 return nil, errors.New("crypto/rsa: unsupported hash function: " + strconv.Itoa(int(h))) 330 } 331 nid := C._goboringcrypto_EVP_MD_type(md) 332 var out []byte 333 var outLen C.uint 334 if priv.withKey(func(key *C.GO_RSA) C.int { 335 out = make([]byte, C._goboringcrypto_RSA_size(key)) 336 return C._goboringcrypto_RSA_sign(nid, base(hashed), C.uint(len(hashed)), 337 base(out), &outLen, key) 338 }) == 0 { 339 return nil, fail("RSA_sign") 340 } 341 return out[:outLen], nil 342 } 343 344 func VerifyRSAPKCS1v15(pub *PublicKeyRSA, h crypto.Hash, hashed, sig []byte) error { 345 if h == 0 { 346 var out []byte 347 var outLen C.size_t 348 if pub.withKey(func(key *C.GO_RSA) C.int { 349 out = make([]byte, C._goboringcrypto_RSA_size(key)) 350 return C._goboringcrypto_RSA_verify_raw(key, &outLen, base(out), 351 C.size_t(len(out)), base(sig), C.size_t(len(sig)), C.GO_RSA_PKCS1_PADDING) 352 }) == 0 { 353 return fail("RSA_verify") 354 } 355 if subtle.ConstantTimeCompare(hashed, out[:outLen]) != 1 { 356 return fail("RSA_verify") 357 } 358 return nil 359 } 360 md := cryptoHashToMD(h) 361 if md == nil { 362 return errors.New("crypto/rsa: unsupported hash function") 363 } 364 nid := C._goboringcrypto_EVP_MD_type(md) 365 if pub.withKey(func(key *C.GO_RSA) C.int { 366 return C._goboringcrypto_RSA_verify(nid, base(hashed), C.size_t(len(hashed)), 367 base(sig), C.size_t(len(sig)), key) 368 }) == 0 { 369 return fail("RSA_verify") 370 } 371 return nil 372 }