1*e7b1675dSTing-Kang Chang// Copyright 2020 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 subtle 18*e7b1675dSTing-Kang Chang 19*e7b1675dSTing-Kang Changimport ( 20*e7b1675dSTing-Kang Chang "errors" 21*e7b1675dSTing-Kang Chang "fmt" 22*e7b1675dSTing-Kang Chang "math/big" 23*e7b1675dSTing-Kang Chang) 24*e7b1675dSTing-Kang Chang 25*e7b1675dSTing-Kang Changvar errUnsupportedEncoding = errors.New("ecdsa: unsupported encoding") 26*e7b1675dSTing-Kang Chang 27*e7b1675dSTing-Kang Chang// ECDSASignature is a struct holding the r and s values of an ECDSA signature. 28*e7b1675dSTing-Kang Changtype ECDSASignature struct { 29*e7b1675dSTing-Kang Chang R, S *big.Int 30*e7b1675dSTing-Kang Chang} 31*e7b1675dSTing-Kang Chang 32*e7b1675dSTing-Kang Chang// NewECDSASignature creates a new ECDSASignature instance. 33*e7b1675dSTing-Kang Changfunc NewECDSASignature(r, s *big.Int) *ECDSASignature { 34*e7b1675dSTing-Kang Chang return &ECDSASignature{R: r, S: s} 35*e7b1675dSTing-Kang Chang} 36*e7b1675dSTing-Kang Chang 37*e7b1675dSTing-Kang Chang// EncodeECDSASignature converts the signature to the given encoding format. 38*e7b1675dSTing-Kang Changfunc (sig *ECDSASignature) EncodeECDSASignature(encoding, curveName string) ([]byte, error) { 39*e7b1675dSTing-Kang Chang var enc []byte 40*e7b1675dSTing-Kang Chang var err error 41*e7b1675dSTing-Kang Chang switch encoding { 42*e7b1675dSTing-Kang Chang case "IEEE_P1363": 43*e7b1675dSTing-Kang Chang enc, err = ieeeP1363Encode(sig, curveName) 44*e7b1675dSTing-Kang Chang case "DER": 45*e7b1675dSTing-Kang Chang enc, err = asn1encode(sig) 46*e7b1675dSTing-Kang Chang default: 47*e7b1675dSTing-Kang Chang err = errUnsupportedEncoding 48*e7b1675dSTing-Kang Chang } 49*e7b1675dSTing-Kang Chang if err != nil { 50*e7b1675dSTing-Kang Chang return nil, fmt.Errorf("ecdsa: can't convert ECDSA signature to %s encoding: %v", encoding, err) 51*e7b1675dSTing-Kang Chang } 52*e7b1675dSTing-Kang Chang return enc, nil 53*e7b1675dSTing-Kang Chang} 54*e7b1675dSTing-Kang Chang 55*e7b1675dSTing-Kang Chang// DecodeECDSASignature creates a new ECDSA signature using the given byte slice. 56*e7b1675dSTing-Kang Chang// The function assumes that the byte slice is the concatenation of the BigEndian 57*e7b1675dSTing-Kang Chang// representation of two big integer r and s. 58*e7b1675dSTing-Kang Changfunc DecodeECDSASignature(encodedBytes []byte, encoding string) (*ECDSASignature, error) { 59*e7b1675dSTing-Kang Chang var sig *ECDSASignature 60*e7b1675dSTing-Kang Chang var err error 61*e7b1675dSTing-Kang Chang switch encoding { 62*e7b1675dSTing-Kang Chang case "IEEE_P1363": 63*e7b1675dSTing-Kang Chang sig, err = ieeeP1363Decode(encodedBytes) 64*e7b1675dSTing-Kang Chang case "DER": 65*e7b1675dSTing-Kang Chang sig, err = asn1decode(encodedBytes) 66*e7b1675dSTing-Kang Chang default: 67*e7b1675dSTing-Kang Chang err = errUnsupportedEncoding 68*e7b1675dSTing-Kang Chang } 69*e7b1675dSTing-Kang Chang if err != nil { 70*e7b1675dSTing-Kang Chang return nil, fmt.Errorf("ecdsa: %s", err) 71*e7b1675dSTing-Kang Chang } 72*e7b1675dSTing-Kang Chang return sig, nil 73*e7b1675dSTing-Kang Chang} 74*e7b1675dSTing-Kang Chang 75*e7b1675dSTing-Kang Chang// ValidateECDSAParams validates ECDSA parameters. 76*e7b1675dSTing-Kang Chang// The hash's strength must not be weaker than the curve's strength. 77*e7b1675dSTing-Kang Chang// DER and IEEE_P1363 encodings are supported. 78*e7b1675dSTing-Kang Changfunc ValidateECDSAParams(hashAlg string, curve string, encoding string) error { 79*e7b1675dSTing-Kang Chang switch encoding { 80*e7b1675dSTing-Kang Chang case "DER": 81*e7b1675dSTing-Kang Chang case "IEEE_P1363": 82*e7b1675dSTing-Kang Chang default: 83*e7b1675dSTing-Kang Chang return errUnsupportedEncoding 84*e7b1675dSTing-Kang Chang } 85*e7b1675dSTing-Kang Chang switch curve { 86*e7b1675dSTing-Kang Chang case "NIST_P256": 87*e7b1675dSTing-Kang Chang if hashAlg != "SHA256" { 88*e7b1675dSTing-Kang Chang return errors.New("invalid hash type, expect SHA-256") 89*e7b1675dSTing-Kang Chang } 90*e7b1675dSTing-Kang Chang case "NIST_P384": 91*e7b1675dSTing-Kang Chang if hashAlg != "SHA384" && hashAlg != "SHA512" { 92*e7b1675dSTing-Kang Chang return errors.New("invalid hash type, expect SHA-384 or SHA-512") 93*e7b1675dSTing-Kang Chang } 94*e7b1675dSTing-Kang Chang case "NIST_P521": 95*e7b1675dSTing-Kang Chang if hashAlg != "SHA512" { 96*e7b1675dSTing-Kang Chang return errors.New("invalid hash type, expect SHA-512") 97*e7b1675dSTing-Kang Chang } 98*e7b1675dSTing-Kang Chang default: 99*e7b1675dSTing-Kang Chang return fmt.Errorf("unsupported curve: %s", curve) 100*e7b1675dSTing-Kang Chang } 101*e7b1675dSTing-Kang Chang return nil 102*e7b1675dSTing-Kang Chang} 103