1// Copyright 2020 Google LLC 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); 4// you may not use this file except in compliance with the License. 5// You may obtain a copy of the License at 6// 7// http://www.apache.org/licenses/LICENSE-2.0 8// 9// Unless required by applicable law or agreed to in writing, software 10// distributed under the License is distributed on an "AS IS" BASIS, 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12// See the License for the specific language governing permissions and 13// limitations under the License. 14// 15//////////////////////////////////////////////////////////////////////////////// 16 17package subtle 18 19import ( 20 "errors" 21 "fmt" 22 "math/big" 23) 24 25var errUnsupportedEncoding = errors.New("ecdsa: unsupported encoding") 26 27// ECDSASignature is a struct holding the r and s values of an ECDSA signature. 28type ECDSASignature struct { 29 R, S *big.Int 30} 31 32// NewECDSASignature creates a new ECDSASignature instance. 33func NewECDSASignature(r, s *big.Int) *ECDSASignature { 34 return &ECDSASignature{R: r, S: s} 35} 36 37// EncodeECDSASignature converts the signature to the given encoding format. 38func (sig *ECDSASignature) EncodeECDSASignature(encoding, curveName string) ([]byte, error) { 39 var enc []byte 40 var err error 41 switch encoding { 42 case "IEEE_P1363": 43 enc, err = ieeeP1363Encode(sig, curveName) 44 case "DER": 45 enc, err = asn1encode(sig) 46 default: 47 err = errUnsupportedEncoding 48 } 49 if err != nil { 50 return nil, fmt.Errorf("ecdsa: can't convert ECDSA signature to %s encoding: %v", encoding, err) 51 } 52 return enc, nil 53} 54 55// DecodeECDSASignature creates a new ECDSA signature using the given byte slice. 56// The function assumes that the byte slice is the concatenation of the BigEndian 57// representation of two big integer r and s. 58func DecodeECDSASignature(encodedBytes []byte, encoding string) (*ECDSASignature, error) { 59 var sig *ECDSASignature 60 var err error 61 switch encoding { 62 case "IEEE_P1363": 63 sig, err = ieeeP1363Decode(encodedBytes) 64 case "DER": 65 sig, err = asn1decode(encodedBytes) 66 default: 67 err = errUnsupportedEncoding 68 } 69 if err != nil { 70 return nil, fmt.Errorf("ecdsa: %s", err) 71 } 72 return sig, nil 73} 74 75// ValidateECDSAParams validates ECDSA parameters. 76// The hash's strength must not be weaker than the curve's strength. 77// DER and IEEE_P1363 encodings are supported. 78func ValidateECDSAParams(hashAlg string, curve string, encoding string) error { 79 switch encoding { 80 case "DER": 81 case "IEEE_P1363": 82 default: 83 return errUnsupportedEncoding 84 } 85 switch curve { 86 case "NIST_P256": 87 if hashAlg != "SHA256" { 88 return errors.New("invalid hash type, expect SHA-256") 89 } 90 case "NIST_P384": 91 if hashAlg != "SHA384" && hashAlg != "SHA512" { 92 return errors.New("invalid hash type, expect SHA-384 or SHA-512") 93 } 94 case "NIST_P521": 95 if hashAlg != "SHA512" { 96 return errors.New("invalid hash type, expect SHA-512") 97 } 98 default: 99 return fmt.Errorf("unsupported curve: %s", curve) 100 } 101 return nil 102} 103