Source file src/crypto/internal/fips140/rsa/pkcs1v15.go

     1  // Copyright 2009 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  package rsa
     6  
     7  // This file implements signing and verification using PKCS #1 v1.5 signatures.
     8  
     9  import (
    10  	"bytes"
    11  	"crypto/internal/fips140"
    12  	"errors"
    13  )
    14  
    15  // These are ASN1 DER structures:
    16  //
    17  //	DigestInfo ::= SEQUENCE {
    18  //	  digestAlgorithm AlgorithmIdentifier,
    19  //	  digest OCTET STRING
    20  //	}
    21  //
    22  // For performance, we don't use the generic ASN1 encoder. Rather, we
    23  // precompute a prefix of the digest value that makes a valid ASN1 DER string
    24  // with the correct contents.
    25  //
    26  // For any new entry, also add the size to [hashSize], and if applicable, add
    27  // the hash name to [checkApprovedHashName].
    28  var hashPrefixes = map[string][]byte{
    29  	"MD5":         {0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x05, 0x05, 0x00, 0x04, 0x10},
    30  	"SHA-1":       {0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14},
    31  	"SHA-224":     {0x30, 0x2d, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04, 0x05, 0x00, 0x04, 0x1c},
    32  	"SHA-256":     {0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20},
    33  	"SHA-384":     {0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x05, 0x00, 0x04, 0x30},
    34  	"SHA-512":     {0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, 0x00, 0x04, 0x40},
    35  	"SHA-512/224": {0x30, 0x2d, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x05, 0x05, 0x00, 0x04, 0x1C},
    36  	"SHA-512/256": {0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x06, 0x05, 0x00, 0x04, 0x20},
    37  	"SHA3-224":    {0x30, 0x2d, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x07, 0x05, 0x00, 0x04, 0x1C},
    38  	"SHA3-256":    {0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x08, 0x05, 0x00, 0x04, 0x20},
    39  	"SHA3-384":    {0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x09, 0x05, 0x00, 0x04, 0x30},
    40  	"SHA3-512":    {0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x0a, 0x05, 0x00, 0x04, 0x40},
    41  	"MD5+SHA1":    {}, // A special TLS case which doesn't use an ASN1 prefix.
    42  	"RIPEMD-160":  {0x30, 0x20, 0x30, 0x08, 0x06, 0x06, 0x28, 0xcf, 0x06, 0x03, 0x00, 0x31, 0x04, 0x14},
    43  }
    44  
    45  // SignPKCS1v15 calculates an RSASSA-PKCS1-v1.5 signature.
    46  //
    47  // hash is the name of the hash function as returned by [crypto.Hash.String]
    48  // or the empty string to indicate that the message is signed directly.
    49  func SignPKCS1v15(priv *PrivateKey, hash string, hashed []byte) ([]byte, error) {
    50  	fipsSelfTest()
    51  	fips140.RecordApproved()
    52  	checkApprovedHashName(hash)
    53  
    54  	return signPKCS1v15(priv, hash, hashed)
    55  }
    56  
    57  func signPKCS1v15(priv *PrivateKey, hash string, hashed []byte) ([]byte, error) {
    58  	em, err := pkcs1v15ConstructEM(&priv.pub, hash, hashed)
    59  	if err != nil {
    60  		return nil, err
    61  	}
    62  
    63  	return decrypt(priv, em, withCheck)
    64  }
    65  
    66  func pkcs1v15ConstructEM(pub *PublicKey, hash string, hashed []byte) ([]byte, error) {
    67  	// Special case: "" is used to indicate that the data is signed directly.
    68  	var prefix []byte
    69  	if hash != "" {
    70  		var ok bool
    71  		prefix, ok = hashPrefixes[hash]
    72  		if !ok {
    73  			return nil, errors.New("crypto/rsa: unsupported hash function")
    74  		}
    75  		if len(hashed) != hashSize(hash) {
    76  			return nil, errors.New("crypto/rsa: hashed message length does not match hash function")
    77  		}
    78  	}
    79  
    80  	// EM = 0x00 || 0x01 || PS || 0x00 || T
    81  	k := pub.Size()
    82  	if k < len(prefix)+len(hashed)+2+8+1 {
    83  		return nil, ErrMessageTooLong
    84  	}
    85  	em := make([]byte, k)
    86  	em[1] = 1
    87  	for i := 2; i < k-len(prefix)-len(hashed)-1; i++ {
    88  		em[i] = 0xff
    89  	}
    90  	copy(em[k-len(prefix)-len(hashed):], prefix)
    91  	copy(em[k-len(hashed):], hashed)
    92  	return em, nil
    93  }
    94  
    95  // VerifyPKCS1v15 verifies an RSASSA-PKCS1-v1.5 signature.
    96  //
    97  // hash is the name of the hash function as returned by [crypto.Hash.String]
    98  // or the empty string to indicate that the message is signed directly.
    99  func VerifyPKCS1v15(pub *PublicKey, hash string, hashed []byte, sig []byte) error {
   100  	fipsSelfTest()
   101  	fips140.RecordApproved()
   102  	checkApprovedHashName(hash)
   103  
   104  	return verifyPKCS1v15(pub, hash, hashed, sig)
   105  }
   106  
   107  func verifyPKCS1v15(pub *PublicKey, hash string, hashed []byte, sig []byte) error {
   108  	if fipsApproved, err := checkPublicKey(pub); err != nil {
   109  		return err
   110  	} else if !fipsApproved {
   111  		fips140.RecordNonApproved()
   112  	}
   113  
   114  	// RFC 8017 Section 8.2.2: If the length of the signature S is not k
   115  	// octets (where k is the length in octets of the RSA modulus n), output
   116  	// "invalid signature" and stop.
   117  	if pub.Size() != len(sig) {
   118  		return ErrVerification
   119  	}
   120  
   121  	em, err := encrypt(pub, sig)
   122  	if err != nil {
   123  		return ErrVerification
   124  	}
   125  
   126  	expected, err := pkcs1v15ConstructEM(pub, hash, hashed)
   127  	if err != nil {
   128  		return ErrVerification
   129  	}
   130  	if !bytes.Equal(em, expected) {
   131  		return ErrVerification
   132  	}
   133  
   134  	return nil
   135  }
   136  
   137  func hashSize(hash string) int {
   138  	switch hash {
   139  	case "MD5":
   140  		return 16
   141  	case "SHA-1", "RIPEMD-160":
   142  		return 20
   143  	case "SHA-224", "SHA-512/224", "SHA3-224":
   144  		return 28
   145  	case "SHA-256", "SHA-512/256", "SHA3-256":
   146  		return 32
   147  	case "SHA-384", "SHA3-384":
   148  		return 48
   149  	case "SHA-512", "SHA3-512":
   150  		return 64
   151  	case "MD5+SHA1":
   152  		return 36
   153  	default:
   154  		return -1
   155  	}
   156  }
   157  
   158  func checkApprovedHashName(hash string) {
   159  	switch hash {
   160  	case "SHA-224", "SHA-256", "SHA-384", "SHA-512", "SHA-512/224", "SHA-512/256",
   161  		"SHA3-224", "SHA3-256", "SHA3-384", "SHA3-512":
   162  	default:
   163  		fips140.RecordNonApproved()
   164  	}
   165  }
   166  

View as plain text