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  var hashPrefixes = map[string][]byte{
    26  	"MD5":         {0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x05, 0x05, 0x00, 0x04, 0x10},
    27  	"SHA-1":       {0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14},
    28  	"SHA-224":     {0x30, 0x2d, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04, 0x05, 0x00, 0x04, 0x1c},
    29  	"SHA-256":     {0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20},
    30  	"SHA-384":     {0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x05, 0x00, 0x04, 0x30},
    31  	"SHA-512":     {0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, 0x00, 0x04, 0x40},
    32  	"SHA-512/224": {0x30, 0x2d, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x05, 0x05, 0x00, 0x04, 0x1C},
    33  	"SHA-512/256": {0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x06, 0x05, 0x00, 0x04, 0x20},
    34  	"SHA3-224":    {0x30, 0x2d, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x07, 0x05, 0x00, 0x04, 0x1C},
    35  	"SHA3-256":    {0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x08, 0x05, 0x00, 0x04, 0x20},
    36  	"SHA3-384":    {0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x09, 0x05, 0x00, 0x04, 0x30},
    37  	"SHA3-512":    {0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x0a, 0x05, 0x00, 0x04, 0x40},
    38  	"MD5+SHA1":    {}, // A special TLS case which doesn't use an ASN1 prefix.
    39  	"RIPEMD-160":  {0x30, 0x20, 0x30, 0x08, 0x06, 0x06, 0x28, 0xcf, 0x06, 0x03, 0x00, 0x31, 0x04, 0x14},
    40  }
    41  
    42  // SignPKCS1v15 calculates an RSASSA-PKCS1-v1.5 signature.
    43  //
    44  // hash is the name of the hash function as returned by [crypto.Hash.String]
    45  // or the empty string to indicate that the message is signed directly.
    46  func SignPKCS1v15(priv *PrivateKey, hash string, hashed []byte) ([]byte, error) {
    47  	fipsSelfTest()
    48  	fips140.RecordApproved()
    49  	checkApprovedHashName(hash)
    50  
    51  	return signPKCS1v15(priv, hash, hashed)
    52  }
    53  
    54  func signPKCS1v15(priv *PrivateKey, hash string, hashed []byte) ([]byte, error) {
    55  	em, err := pkcs1v15ConstructEM(&priv.pub, hash, hashed)
    56  	if err != nil {
    57  		return nil, err
    58  	}
    59  
    60  	return decrypt(priv, em, withCheck)
    61  }
    62  
    63  func pkcs1v15ConstructEM(pub *PublicKey, hash string, hashed []byte) ([]byte, error) {
    64  	// Special case: "" is used to indicate that the data is signed directly.
    65  	var prefix []byte
    66  	if hash != "" {
    67  		var ok bool
    68  		prefix, ok = hashPrefixes[hash]
    69  		if !ok {
    70  			return nil, errors.New("crypto/rsa: unsupported hash function")
    71  		}
    72  	}
    73  
    74  	// EM = 0x00 || 0x01 || PS || 0x00 || T
    75  	k := pub.Size()
    76  	if k < len(prefix)+len(hashed)+2+8+1 {
    77  		return nil, ErrMessageTooLong
    78  	}
    79  	em := make([]byte, k)
    80  	em[1] = 1
    81  	for i := 2; i < k-len(prefix)-len(hashed)-1; i++ {
    82  		em[i] = 0xff
    83  	}
    84  	copy(em[k-len(prefix)-len(hashed):], prefix)
    85  	copy(em[k-len(hashed):], hashed)
    86  	return em, nil
    87  }
    88  
    89  // VerifyPKCS1v15 verifies an RSASSA-PKCS1-v1.5 signature.
    90  //
    91  // hash is the name of the hash function as returned by [crypto.Hash.String]
    92  // or the empty string to indicate that the message is signed directly.
    93  func VerifyPKCS1v15(pub *PublicKey, hash string, hashed []byte, sig []byte) error {
    94  	fipsSelfTest()
    95  	fips140.RecordApproved()
    96  	checkApprovedHashName(hash)
    97  
    98  	return verifyPKCS1v15(pub, hash, hashed, sig)
    99  }
   100  
   101  func verifyPKCS1v15(pub *PublicKey, hash string, hashed []byte, sig []byte) error {
   102  	if fipsApproved, err := checkPublicKey(pub); err != nil {
   103  		return err
   104  	} else if !fipsApproved {
   105  		fips140.RecordNonApproved()
   106  	}
   107  
   108  	// RFC 8017 Section 8.2.2: If the length of the signature S is not k
   109  	// octets (where k is the length in octets of the RSA modulus n), output
   110  	// "invalid signature" and stop.
   111  	if pub.Size() != len(sig) {
   112  		return ErrVerification
   113  	}
   114  
   115  	em, err := encrypt(pub, sig)
   116  	if err != nil {
   117  		return ErrVerification
   118  	}
   119  
   120  	expected, err := pkcs1v15ConstructEM(pub, hash, hashed)
   121  	if err != nil {
   122  		return ErrVerification
   123  	}
   124  	if !bytes.Equal(em, expected) {
   125  		return ErrVerification
   126  	}
   127  
   128  	return nil
   129  }
   130  
   131  func checkApprovedHashName(hash string) {
   132  	switch hash {
   133  	case "SHA-224", "SHA-256", "SHA-384", "SHA-512", "SHA-512/224", "SHA-512/256",
   134  		"SHA3-224", "SHA3-256", "SHA3-384", "SHA3-512":
   135  	default:
   136  		fips140.RecordNonApproved()
   137  	}
   138  }
   139  

View as plain text