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 Chang// Package subtle provides common methods needed in subtle implementations. 18*e7b1675dSTing-Kang Changpackage subtle 19*e7b1675dSTing-Kang Chang 20*e7b1675dSTing-Kang Changimport ( 21*e7b1675dSTing-Kang Chang "crypto/elliptic" 22*e7b1675dSTing-Kang Chang "crypto/sha1" 23*e7b1675dSTing-Kang Chang "crypto/sha256" 24*e7b1675dSTing-Kang Chang "crypto/sha512" 25*e7b1675dSTing-Kang Chang "encoding/hex" 26*e7b1675dSTing-Kang Chang "errors" 27*e7b1675dSTing-Kang Chang "hash" 28*e7b1675dSTing-Kang Chang "math/big" 29*e7b1675dSTing-Kang Chang) 30*e7b1675dSTing-Kang Chang 31*e7b1675dSTing-Kang Changvar errNilHashFunc = errors.New("nil hash function") 32*e7b1675dSTing-Kang Chang 33*e7b1675dSTing-Kang Chang// hashDigestSize maps hash algorithms to their digest size in bytes. 34*e7b1675dSTing-Kang Changvar hashDigestSize = map[string]uint32{ 35*e7b1675dSTing-Kang Chang "SHA1": uint32(20), 36*e7b1675dSTing-Kang Chang "SHA224": uint32(28), 37*e7b1675dSTing-Kang Chang "SHA256": uint32(32), 38*e7b1675dSTing-Kang Chang "SHA384": uint32(48), 39*e7b1675dSTing-Kang Chang "SHA512": uint32(64), 40*e7b1675dSTing-Kang Chang} 41*e7b1675dSTing-Kang Chang 42*e7b1675dSTing-Kang Chang// GetHashDigestSize returns the digest size of the specified hash algorithm. 43*e7b1675dSTing-Kang Changfunc GetHashDigestSize(hash string) (uint32, error) { 44*e7b1675dSTing-Kang Chang digestSize, ok := hashDigestSize[hash] 45*e7b1675dSTing-Kang Chang if !ok { 46*e7b1675dSTing-Kang Chang return 0, errors.New("invalid hash algorithm") 47*e7b1675dSTing-Kang Chang } 48*e7b1675dSTing-Kang Chang return digestSize, nil 49*e7b1675dSTing-Kang Chang} 50*e7b1675dSTing-Kang Chang 51*e7b1675dSTing-Kang Chang// TODO(ckl): Perhaps return an explicit error instead of ""/nil for the 52*e7b1675dSTing-Kang Chang// following functions. 53*e7b1675dSTing-Kang Chang 54*e7b1675dSTing-Kang Chang// ConvertHashName converts different forms of a hash name to the 55*e7b1675dSTing-Kang Chang// hash name that tink recognizes. 56*e7b1675dSTing-Kang Changfunc ConvertHashName(name string) string { 57*e7b1675dSTing-Kang Chang switch name { 58*e7b1675dSTing-Kang Chang case "SHA-224": 59*e7b1675dSTing-Kang Chang return "SHA224" 60*e7b1675dSTing-Kang Chang case "SHA-256": 61*e7b1675dSTing-Kang Chang return "SHA256" 62*e7b1675dSTing-Kang Chang case "SHA-384": 63*e7b1675dSTing-Kang Chang return "SHA384" 64*e7b1675dSTing-Kang Chang case "SHA-512": 65*e7b1675dSTing-Kang Chang return "SHA512" 66*e7b1675dSTing-Kang Chang case "SHA-1": 67*e7b1675dSTing-Kang Chang return "SHA1" 68*e7b1675dSTing-Kang Chang default: 69*e7b1675dSTing-Kang Chang return "" 70*e7b1675dSTing-Kang Chang } 71*e7b1675dSTing-Kang Chang} 72*e7b1675dSTing-Kang Chang 73*e7b1675dSTing-Kang Chang// ConvertCurveName converts different forms of a curve name to the 74*e7b1675dSTing-Kang Chang// name that tink recognizes. 75*e7b1675dSTing-Kang Changfunc ConvertCurveName(name string) string { 76*e7b1675dSTing-Kang Chang switch name { 77*e7b1675dSTing-Kang Chang case "secp256r1", "P-256": 78*e7b1675dSTing-Kang Chang return "NIST_P256" 79*e7b1675dSTing-Kang Chang case "secp384r1", "P-384": 80*e7b1675dSTing-Kang Chang return "NIST_P384" 81*e7b1675dSTing-Kang Chang case "secp521r1", "P-521": 82*e7b1675dSTing-Kang Chang return "NIST_P521" 83*e7b1675dSTing-Kang Chang default: 84*e7b1675dSTing-Kang Chang return "" 85*e7b1675dSTing-Kang Chang } 86*e7b1675dSTing-Kang Chang} 87*e7b1675dSTing-Kang Chang 88*e7b1675dSTing-Kang Chang// GetHashFunc returns the corresponding hash function of the given hash name. 89*e7b1675dSTing-Kang Changfunc GetHashFunc(hash string) func() hash.Hash { 90*e7b1675dSTing-Kang Chang switch hash { 91*e7b1675dSTing-Kang Chang case "SHA1": 92*e7b1675dSTing-Kang Chang return sha1.New 93*e7b1675dSTing-Kang Chang case "SHA224": 94*e7b1675dSTing-Kang Chang return sha256.New224 95*e7b1675dSTing-Kang Chang case "SHA256": 96*e7b1675dSTing-Kang Chang return sha256.New 97*e7b1675dSTing-Kang Chang case "SHA384": 98*e7b1675dSTing-Kang Chang return sha512.New384 99*e7b1675dSTing-Kang Chang case "SHA512": 100*e7b1675dSTing-Kang Chang return sha512.New 101*e7b1675dSTing-Kang Chang default: 102*e7b1675dSTing-Kang Chang return nil 103*e7b1675dSTing-Kang Chang } 104*e7b1675dSTing-Kang Chang} 105*e7b1675dSTing-Kang Chang 106*e7b1675dSTing-Kang Chang// GetCurve returns the curve object that corresponds to the given curve type. 107*e7b1675dSTing-Kang Chang// It returns null if the curve type is not supported. 108*e7b1675dSTing-Kang Changfunc GetCurve(curve string) elliptic.Curve { 109*e7b1675dSTing-Kang Chang switch curve { 110*e7b1675dSTing-Kang Chang case "NIST_P256": 111*e7b1675dSTing-Kang Chang return elliptic.P256() 112*e7b1675dSTing-Kang Chang case "NIST_P384": 113*e7b1675dSTing-Kang Chang return elliptic.P384() 114*e7b1675dSTing-Kang Chang case "NIST_P521": 115*e7b1675dSTing-Kang Chang return elliptic.P521() 116*e7b1675dSTing-Kang Chang default: 117*e7b1675dSTing-Kang Chang return nil 118*e7b1675dSTing-Kang Chang } 119*e7b1675dSTing-Kang Chang} 120*e7b1675dSTing-Kang Chang 121*e7b1675dSTing-Kang Chang// ComputeHash calculates a hash of the given data using the given hash function. 122*e7b1675dSTing-Kang Changfunc ComputeHash(hashFunc func() hash.Hash, data []byte) ([]byte, error) { 123*e7b1675dSTing-Kang Chang if hashFunc == nil { 124*e7b1675dSTing-Kang Chang return nil, errNilHashFunc 125*e7b1675dSTing-Kang Chang } 126*e7b1675dSTing-Kang Chang h := hashFunc() 127*e7b1675dSTing-Kang Chang 128*e7b1675dSTing-Kang Chang _, err := h.Write(data) 129*e7b1675dSTing-Kang Chang if err != nil { 130*e7b1675dSTing-Kang Chang return nil, err 131*e7b1675dSTing-Kang Chang } 132*e7b1675dSTing-Kang Chang 133*e7b1675dSTing-Kang Chang return h.Sum(nil), nil 134*e7b1675dSTing-Kang Chang} 135*e7b1675dSTing-Kang Chang 136*e7b1675dSTing-Kang Chang// NewBigIntFromHex returns a big integer from a hex string. 137*e7b1675dSTing-Kang Changfunc NewBigIntFromHex(s string) (*big.Int, error) { 138*e7b1675dSTing-Kang Chang if len(s)%2 == 1 { 139*e7b1675dSTing-Kang Chang s = "0" + s 140*e7b1675dSTing-Kang Chang } 141*e7b1675dSTing-Kang Chang b, err := hex.DecodeString(s) 142*e7b1675dSTing-Kang Chang if err != nil { 143*e7b1675dSTing-Kang Chang return nil, err 144*e7b1675dSTing-Kang Chang } 145*e7b1675dSTing-Kang Chang ret := new(big.Int).SetBytes(b) 146*e7b1675dSTing-Kang Chang return ret, nil 147*e7b1675dSTing-Kang Chang} 148