xref: /aosp_15_r20/external/tink/go/internal/signature/rsa.go (revision e7b1675dde1b92d52ec075b0a92829627f2c52a5)
1*e7b1675dSTing-Kang Chang// Copyright 2021 Google LLC
2*e7b1675dSTing-Kang Chang//
3*e7b1675dSTing-Kang Chang// Licensed under the Apache License, Version 2.0 (the "License");
4*e7b1675dSTing-Kang Chang// you may not use this file except in compliance with the License.
5*e7b1675dSTing-Kang Chang// You may obtain a copy of the License at
6*e7b1675dSTing-Kang Chang//
7*e7b1675dSTing-Kang Chang//      http://www.apache.org/licenses/LICENSE-2.0
8*e7b1675dSTing-Kang Chang//
9*e7b1675dSTing-Kang Chang// Unless required by applicable law or agreed to in writing, software
10*e7b1675dSTing-Kang Chang// distributed under the License is distributed on an "AS IS" BASIS,
11*e7b1675dSTing-Kang Chang// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*e7b1675dSTing-Kang Chang// See the License for the specific language governing permissions and
13*e7b1675dSTing-Kang Chang// limitations under the License.
14*e7b1675dSTing-Kang Chang//
15*e7b1675dSTing-Kang Chang////////////////////////////////////////////////////////////////////////////////
16*e7b1675dSTing-Kang Chang
17*e7b1675dSTing-Kang Changpackage signature
18*e7b1675dSTing-Kang Chang
19*e7b1675dSTing-Kang Changimport (
20*e7b1675dSTing-Kang Chang	"crypto"
21*e7b1675dSTing-Kang Chang	"crypto/rsa"
22*e7b1675dSTing-Kang Chang	"fmt"
23*e7b1675dSTing-Kang Chang	"hash"
24*e7b1675dSTing-Kang Chang
25*e7b1675dSTing-Kang Chang	"github.com/google/tink/go/subtle"
26*e7b1675dSTing-Kang Chang	"github.com/google/tink/go/tink"
27*e7b1675dSTing-Kang Chang)
28*e7b1675dSTing-Kang Chang
29*e7b1675dSTing-Kang Changconst (
30*e7b1675dSTing-Kang Chang	rsaMinModulusSizeInBits  = 2048
31*e7b1675dSTing-Kang Chang	rsaDefaultPublicExponent = 65537
32*e7b1675dSTing-Kang Chang)
33*e7b1675dSTing-Kang Chang
34*e7b1675dSTing-Kang Chang// RSAValidModulusSizeInBits the size in bits for an RSA key.
35*e7b1675dSTing-Kang Changfunc RSAValidModulusSizeInBits(m int) error {
36*e7b1675dSTing-Kang Chang	if m < rsaMinModulusSizeInBits {
37*e7b1675dSTing-Kang Chang		return fmt.Errorf("modulus size too small, must be >= %d", rsaMinModulusSizeInBits)
38*e7b1675dSTing-Kang Chang	}
39*e7b1675dSTing-Kang Chang	return nil
40*e7b1675dSTing-Kang Chang}
41*e7b1675dSTing-Kang Chang
42*e7b1675dSTing-Kang Chang// RSAValidPublicExponent validates a public RSA exponent.
43*e7b1675dSTing-Kang Changfunc RSAValidPublicExponent(e int) error {
44*e7b1675dSTing-Kang Chang	// crypto/rsa uses the following hardcoded public exponent value.
45*e7b1675dSTing-Kang Chang	if e != rsaDefaultPublicExponent {
46*e7b1675dSTing-Kang Chang		return fmt.Errorf("invalid public exponent")
47*e7b1675dSTing-Kang Chang	}
48*e7b1675dSTing-Kang Chang	return nil
49*e7b1675dSTing-Kang Chang}
50*e7b1675dSTing-Kang Chang
51*e7b1675dSTing-Kang Chang// HashSafeForSignature checks whether a hash function is safe to use with digital signatures
52*e7b1675dSTing-Kang Chang// that require collision resistance.
53*e7b1675dSTing-Kang Changfunc HashSafeForSignature(hashAlg string) error {
54*e7b1675dSTing-Kang Chang	switch hashAlg {
55*e7b1675dSTing-Kang Chang	case "SHA256", "SHA384", "SHA512":
56*e7b1675dSTing-Kang Chang		return nil
57*e7b1675dSTing-Kang Chang	default:
58*e7b1675dSTing-Kang Chang		return fmt.Errorf("hash function not safe for digital signatures: %q", hashAlg)
59*e7b1675dSTing-Kang Chang	}
60*e7b1675dSTing-Kang Chang}
61*e7b1675dSTing-Kang Chang
62*e7b1675dSTing-Kang Changconst (
63*e7b1675dSTing-Kang Chang	testMsg          = "Tink and Wycheproof."
64*e7b1675dSTing-Kang Chang	signVerifyErrMsg = "signing with private key followed by verifying with public key failed, the key may be corrupted"
65*e7b1675dSTing-Kang Chang)
66*e7b1675dSTing-Kang Chang
67*e7b1675dSTing-Kang Chang// Validate_RSA_SSA_PKCS1 validates that the corresponding private key is valid by signing and verifying a message.
68*e7b1675dSTing-Kang Changfunc Validate_RSA_SSA_PKCS1(hashAlg string, privKey *rsa.PrivateKey) error {
69*e7b1675dSTing-Kang Chang	signer, err := New_RSA_SSA_PKCS1_Signer(hashAlg, privKey)
70*e7b1675dSTing-Kang Chang	if err != nil {
71*e7b1675dSTing-Kang Chang		return err
72*e7b1675dSTing-Kang Chang	}
73*e7b1675dSTing-Kang Chang	verifier, err := New_RSA_SSA_PKCS1_Verifier(hashAlg, &privKey.PublicKey)
74*e7b1675dSTing-Kang Chang	if err != nil {
75*e7b1675dSTing-Kang Chang		return err
76*e7b1675dSTing-Kang Chang	}
77*e7b1675dSTing-Kang Chang	if err := validateSignerVerifier(signer, verifier); err != nil {
78*e7b1675dSTing-Kang Chang		return fmt.Errorf("RSA-SSA-PKCS1: %q", signVerifyErrMsg)
79*e7b1675dSTing-Kang Chang	}
80*e7b1675dSTing-Kang Chang	return nil
81*e7b1675dSTing-Kang Chang}
82*e7b1675dSTing-Kang Chang
83*e7b1675dSTing-Kang Chang// Validate_RSA_SSA_PSS validates that the corresponding private key is valid by signing and verifying a message.
84*e7b1675dSTing-Kang Changfunc Validate_RSA_SSA_PSS(hashAlg string, saltLen int, privKey *rsa.PrivateKey) error {
85*e7b1675dSTing-Kang Chang	signer, err := New_RSA_SSA_PSS_Signer(hashAlg, saltLen, privKey)
86*e7b1675dSTing-Kang Chang	if err != nil {
87*e7b1675dSTing-Kang Chang		return err
88*e7b1675dSTing-Kang Chang	}
89*e7b1675dSTing-Kang Chang	verifier, err := New_RSA_SSA_PSS_Verifier(hashAlg, saltLen, &privKey.PublicKey)
90*e7b1675dSTing-Kang Chang	if err != nil {
91*e7b1675dSTing-Kang Chang		return err
92*e7b1675dSTing-Kang Chang	}
93*e7b1675dSTing-Kang Chang	if err := validateSignerVerifier(signer, verifier); err != nil {
94*e7b1675dSTing-Kang Chang		return fmt.Errorf("RSA-SSA-PSS: %q", signVerifyErrMsg)
95*e7b1675dSTing-Kang Chang	}
96*e7b1675dSTing-Kang Chang	return nil
97*e7b1675dSTing-Kang Chang}
98*e7b1675dSTing-Kang Chang
99*e7b1675dSTing-Kang Changfunc validateSignerVerifier(signer tink.Signer, verifier tink.Verifier) error {
100*e7b1675dSTing-Kang Chang	signature, err := signer.Sign([]byte(testMsg))
101*e7b1675dSTing-Kang Chang	if err != nil {
102*e7b1675dSTing-Kang Chang		return err
103*e7b1675dSTing-Kang Chang	}
104*e7b1675dSTing-Kang Chang	if err := verifier.Verify([]byte(signature), []byte(testMsg)); err != nil {
105*e7b1675dSTing-Kang Chang		return err
106*e7b1675dSTing-Kang Chang	}
107*e7b1675dSTing-Kang Chang	return nil
108*e7b1675dSTing-Kang Chang}
109*e7b1675dSTing-Kang Chang
110*e7b1675dSTing-Kang Changfunc validRSAPublicKey(publicKey *rsa.PublicKey) error {
111*e7b1675dSTing-Kang Chang	if err := RSAValidModulusSizeInBits(publicKey.N.BitLen()); err != nil {
112*e7b1675dSTing-Kang Chang		return err
113*e7b1675dSTing-Kang Chang	}
114*e7b1675dSTing-Kang Chang	return RSAValidPublicExponent(publicKey.E)
115*e7b1675dSTing-Kang Chang}
116*e7b1675dSTing-Kang Chang
117*e7b1675dSTing-Kang Changfunc hashID(hashAlg string) (crypto.Hash, error) {
118*e7b1675dSTing-Kang Chang	switch hashAlg {
119*e7b1675dSTing-Kang Chang	case "SHA256":
120*e7b1675dSTing-Kang Chang		return crypto.SHA256, nil
121*e7b1675dSTing-Kang Chang	case "SHA384":
122*e7b1675dSTing-Kang Chang		return crypto.SHA384, nil
123*e7b1675dSTing-Kang Chang	case "SHA512":
124*e7b1675dSTing-Kang Chang		return crypto.SHA512, nil
125*e7b1675dSTing-Kang Chang	default:
126*e7b1675dSTing-Kang Chang		return 0, fmt.Errorf("invalid hash function: %q", hashAlg)
127*e7b1675dSTing-Kang Chang	}
128*e7b1675dSTing-Kang Chang}
129*e7b1675dSTing-Kang Chang
130*e7b1675dSTing-Kang Changfunc rsaHashFunc(hashAlg string) (func() hash.Hash, crypto.Hash, error) {
131*e7b1675dSTing-Kang Chang	if err := HashSafeForSignature(hashAlg); err != nil {
132*e7b1675dSTing-Kang Chang		return nil, 0, err
133*e7b1675dSTing-Kang Chang	}
134*e7b1675dSTing-Kang Chang	hashFunc := subtle.GetHashFunc(hashAlg)
135*e7b1675dSTing-Kang Chang	if hashFunc == nil {
136*e7b1675dSTing-Kang Chang		return nil, 0, fmt.Errorf("invalid hash function: %q", hashAlg)
137*e7b1675dSTing-Kang Chang	}
138*e7b1675dSTing-Kang Chang	hashID, err := hashID(hashAlg)
139*e7b1675dSTing-Kang Chang	if err != nil {
140*e7b1675dSTing-Kang Chang		return nil, 0, err
141*e7b1675dSTing-Kang Chang	}
142*e7b1675dSTing-Kang Chang	return hashFunc, hashID, nil
143*e7b1675dSTing-Kang Chang}
144