Source file src/crypto/internal/boring/rsa.go

     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 && !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, mgfHash 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 pkey, ctx, 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 pkey, ctx, fail("EVP_PKEY_set1_RSA")
   135  	}
   136  	ctx = C._goboringcrypto_EVP_PKEY_CTX_new(pkey, nil)
   137  	if ctx == nil {
   138  		return pkey, ctx, fail("EVP_PKEY_CTX_new")
   139  	}
   140  	if init(ctx) == 0 {
   141  		return pkey, ctx, fail("EVP_PKEY_operation_init")
   142  	}
   143  	if C._goboringcrypto_EVP_PKEY_CTX_set_rsa_padding(ctx, padding) == 0 {
   144  		return pkey, ctx, 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 pkey, ctx, errors.New("crypto/rsa: unsupported hash function")
   150  		}
   151  		mgfMD := hashToMD(mgfHash)
   152  		if mgfMD == nil {
   153  			return pkey, ctx, errors.New("crypto/rsa: unsupported hash function")
   154  		}
   155  		if C._goboringcrypto_EVP_PKEY_CTX_set_rsa_oaep_md(ctx, md) == 0 {
   156  			return pkey, ctx, fail("EVP_PKEY_set_rsa_oaep_md")
   157  		}
   158  		if C._goboringcrypto_EVP_PKEY_CTX_set_rsa_mgf1_md(ctx, mgfMD) == 0 {
   159  			return pkey, ctx, fail("EVP_PKEY_set_rsa_mgf1_md")
   160  		}
   161  		// ctx takes ownership of label, so malloc a copy for BoringCrypto to free.
   162  		clabel := (*C.uint8_t)(C._goboringcrypto_OPENSSL_malloc(C.size_t(len(label))))
   163  		if clabel == nil {
   164  			return pkey, ctx, fail("OPENSSL_malloc")
   165  		}
   166  		copy((*[1 << 30]byte)(unsafe.Pointer(clabel))[:len(label)], label)
   167  		if C._goboringcrypto_EVP_PKEY_CTX_set0_rsa_oaep_label(ctx, clabel, C.size_t(len(label))) == 0 {
   168  			return pkey, ctx, fail("EVP_PKEY_CTX_set0_rsa_oaep_label")
   169  		}
   170  	}
   171  	if padding == C.GO_RSA_PKCS1_PSS_PADDING {
   172  		if saltLen != 0 {
   173  			if C._goboringcrypto_EVP_PKEY_CTX_set_rsa_pss_saltlen(ctx, C.int(saltLen)) == 0 {
   174  				return pkey, ctx, fail("EVP_PKEY_set_rsa_pss_saltlen")
   175  			}
   176  		}
   177  		md := cryptoHashToMD(ch)
   178  		if md == nil {
   179  			return pkey, ctx, errors.New("crypto/rsa: unsupported hash function")
   180  		}
   181  		if C._goboringcrypto_EVP_PKEY_CTX_set_rsa_mgf1_md(ctx, md) == 0 {
   182  			return pkey, ctx, fail("EVP_PKEY_set_rsa_mgf1_md")
   183  		}
   184  	}
   185  
   186  	return pkey, ctx, nil
   187  }
   188  
   189  func cryptRSA(withKey func(func(*C.GO_RSA) C.int) C.int,
   190  	padding C.int, h, mgfHash hash.Hash, label []byte, saltLen int, ch crypto.Hash,
   191  	init func(*C.GO_EVP_PKEY_CTX) C.int,
   192  	crypt func(*C.GO_EVP_PKEY_CTX, *C.uint8_t, *C.size_t, *C.uint8_t, C.size_t) C.int,
   193  	in []byte) ([]byte, error) {
   194  
   195  	pkey, ctx, err := setupRSA(withKey, padding, h, mgfHash, label, saltLen, ch, init)
   196  	if err != nil {
   197  		return nil, err
   198  	}
   199  	defer C._goboringcrypto_EVP_PKEY_free(pkey)
   200  	defer C._goboringcrypto_EVP_PKEY_CTX_free(ctx)
   201  
   202  	var outLen C.size_t
   203  	if crypt(ctx, nil, &outLen, base(in), C.size_t(len(in))) == 0 {
   204  		return nil, fail("EVP_PKEY_decrypt/encrypt")
   205  	}
   206  	out := make([]byte, outLen)
   207  	if crypt(ctx, base(out), &outLen, base(in), C.size_t(len(in))) == 0 {
   208  		return nil, fail("EVP_PKEY_decrypt/encrypt")
   209  	}
   210  	return out[:outLen], nil
   211  }
   212  
   213  func DecryptRSAOAEP(h, mgfHash hash.Hash, priv *PrivateKeyRSA, ciphertext, label []byte) ([]byte, error) {
   214  	return cryptRSA(priv.withKey, C.GO_RSA_PKCS1_OAEP_PADDING, h, mgfHash, label, 0, 0, decryptInit, decrypt, ciphertext)
   215  }
   216  
   217  func EncryptRSAOAEP(h, mgfHash hash.Hash, pub *PublicKeyRSA, msg, label []byte) ([]byte, error) {
   218  	return cryptRSA(pub.withKey, C.GO_RSA_PKCS1_OAEP_PADDING, h, mgfHash, label, 0, 0, encryptInit, encrypt, msg)
   219  }
   220  
   221  func DecryptRSAPKCS1(priv *PrivateKeyRSA, ciphertext []byte) ([]byte, error) {
   222  	return cryptRSA(priv.withKey, C.GO_RSA_PKCS1_PADDING, nil, nil, nil, 0, 0, decryptInit, decrypt, ciphertext)
   223  }
   224  
   225  func EncryptRSAPKCS1(pub *PublicKeyRSA, msg []byte) ([]byte, error) {
   226  	return cryptRSA(pub.withKey, C.GO_RSA_PKCS1_PADDING, nil, nil, nil, 0, 0, encryptInit, encrypt, msg)
   227  }
   228  
   229  func DecryptRSANoPadding(priv *PrivateKeyRSA, ciphertext []byte) ([]byte, error) {
   230  	return cryptRSA(priv.withKey, C.GO_RSA_NO_PADDING, nil, nil, nil, 0, 0, decryptInit, decrypt, ciphertext)
   231  }
   232  
   233  func EncryptRSANoPadding(pub *PublicKeyRSA, msg []byte) ([]byte, error) {
   234  	return cryptRSA(pub.withKey, C.GO_RSA_NO_PADDING, nil, nil, nil, 0, 0, encryptInit, encrypt, msg)
   235  }
   236  
   237  // These dumb wrappers work around the fact that cgo functions cannot be used as values directly.
   238  
   239  func decryptInit(ctx *C.GO_EVP_PKEY_CTX) C.int {
   240  	return C._goboringcrypto_EVP_PKEY_decrypt_init(ctx)
   241  }
   242  
   243  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 {
   244  	return C._goboringcrypto_EVP_PKEY_decrypt(ctx, out, outLen, in, inLen)
   245  }
   246  
   247  func encryptInit(ctx *C.GO_EVP_PKEY_CTX) C.int {
   248  	return C._goboringcrypto_EVP_PKEY_encrypt_init(ctx)
   249  }
   250  
   251  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 {
   252  	return C._goboringcrypto_EVP_PKEY_encrypt(ctx, out, outLen, in, inLen)
   253  }
   254  
   255  var invalidSaltLenErr = errors.New("crypto/rsa: PSSOptions.SaltLength cannot be negative")
   256  
   257  func SignRSAPSS(priv *PrivateKeyRSA, h crypto.Hash, hashed []byte, saltLen int) ([]byte, error) {
   258  	md := cryptoHashToMD(h)
   259  	if md == nil {
   260  		return nil, errors.New("crypto/rsa: unsupported hash function")
   261  	}
   262  
   263  	// A salt length of -2 is valid in BoringSSL, but not in crypto/rsa, so reject
   264  	// it, and lengths < -2, before we convert to the BoringSSL sentinel values.
   265  	if saltLen <= -2 {
   266  		return nil, invalidSaltLenErr
   267  	}
   268  
   269  	// BoringSSL uses sentinel salt length values like we do, but the values don't
   270  	// fully match what we use. We both use -1 for salt length equal to hash length,
   271  	// but BoringSSL uses -2 to mean maximal size where we use 0. In the latter
   272  	// case convert to the BoringSSL version.
   273  	if saltLen == 0 {
   274  		saltLen = -2
   275  	}
   276  
   277  	var out []byte
   278  	var outLen C.size_t
   279  	if priv.withKey(func(key *C.GO_RSA) C.int {
   280  		out = make([]byte, C._goboringcrypto_RSA_size(key))
   281  		return C._goboringcrypto_RSA_sign_pss_mgf1(key, &outLen, base(out), C.size_t(len(out)),
   282  			base(hashed), C.size_t(len(hashed)), md, nil, C.int(saltLen))
   283  	}) == 0 {
   284  		return nil, fail("RSA_sign_pss_mgf1")
   285  	}
   286  
   287  	return out[:outLen], nil
   288  }
   289  
   290  func VerifyRSAPSS(pub *PublicKeyRSA, h crypto.Hash, hashed, sig []byte, saltLen int) error {
   291  	md := cryptoHashToMD(h)
   292  	if md == nil {
   293  		return errors.New("crypto/rsa: unsupported hash function")
   294  	}
   295  
   296  	// A salt length of -2 is valid in BoringSSL, but not in crypto/rsa, so reject
   297  	// it, and lengths < -2, before we convert to the BoringSSL sentinel values.
   298  	if saltLen <= -2 {
   299  		return invalidSaltLenErr
   300  	}
   301  
   302  	// BoringSSL uses sentinel salt length values like we do, but the values don't
   303  	// fully match what we use. We both use -1 for salt length equal to hash length,
   304  	// but BoringSSL uses -2 to mean maximal size where we use 0. In the latter
   305  	// case convert to the BoringSSL version.
   306  	if saltLen == 0 {
   307  		saltLen = -2
   308  	}
   309  
   310  	if pub.withKey(func(key *C.GO_RSA) C.int {
   311  		return C._goboringcrypto_RSA_verify_pss_mgf1(key, base(hashed), C.size_t(len(hashed)),
   312  			md, nil, C.int(saltLen), base(sig), C.size_t(len(sig)))
   313  	}) == 0 {
   314  		return fail("RSA_verify_pss_mgf1")
   315  	}
   316  	return nil
   317  }
   318  
   319  func SignRSAPKCS1v15(priv *PrivateKeyRSA, h crypto.Hash, hashed []byte) ([]byte, error) {
   320  	if h == 0 {
   321  		// No hashing.
   322  		var out []byte
   323  		var outLen C.size_t
   324  		if priv.withKey(func(key *C.GO_RSA) C.int {
   325  			out = make([]byte, C._goboringcrypto_RSA_size(key))
   326  			return C._goboringcrypto_RSA_sign_raw(key, &outLen, base(out), C.size_t(len(out)),
   327  				base(hashed), C.size_t(len(hashed)), C.GO_RSA_PKCS1_PADDING)
   328  		}) == 0 {
   329  			return nil, fail("RSA_sign_raw")
   330  		}
   331  		return out[:outLen], nil
   332  	}
   333  
   334  	md := cryptoHashToMD(h)
   335  	if md == nil {
   336  		return nil, errors.New("crypto/rsa: unsupported hash function: " + strconv.Itoa(int(h)))
   337  	}
   338  	nid := C._goboringcrypto_EVP_MD_type(md)
   339  	var out []byte
   340  	var outLen C.uint
   341  	if priv.withKey(func(key *C.GO_RSA) C.int {
   342  		out = make([]byte, C._goboringcrypto_RSA_size(key))
   343  		return C._goboringcrypto_RSA_sign(nid, base(hashed), C.uint(len(hashed)),
   344  			base(out), &outLen, key)
   345  	}) == 0 {
   346  		return nil, fail("RSA_sign")
   347  	}
   348  	return out[:outLen], nil
   349  }
   350  
   351  func VerifyRSAPKCS1v15(pub *PublicKeyRSA, h crypto.Hash, hashed, sig []byte) error {
   352  	if h == 0 {
   353  		var out []byte
   354  		var outLen C.size_t
   355  		if pub.withKey(func(key *C.GO_RSA) C.int {
   356  			out = make([]byte, C._goboringcrypto_RSA_size(key))
   357  			return C._goboringcrypto_RSA_verify_raw(key, &outLen, base(out),
   358  				C.size_t(len(out)), base(sig), C.size_t(len(sig)), C.GO_RSA_PKCS1_PADDING)
   359  		}) == 0 {
   360  			return fail("RSA_verify")
   361  		}
   362  		if subtle.ConstantTimeCompare(hashed, out[:outLen]) != 1 {
   363  			return fail("RSA_verify")
   364  		}
   365  		return nil
   366  	}
   367  	md := cryptoHashToMD(h)
   368  	if md == nil {
   369  		return errors.New("crypto/rsa: unsupported hash function")
   370  	}
   371  	nid := C._goboringcrypto_EVP_MD_type(md)
   372  	if pub.withKey(func(key *C.GO_RSA) C.int {
   373  		return C._goboringcrypto_RSA_verify(nid, base(hashed), C.size_t(len(hashed)),
   374  			base(sig), C.size_t(len(sig)), key)
   375  	}) == 0 {
   376  		return fail("RSA_verify")
   377  	}
   378  	return nil
   379  }
   380  

View as plain text