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_test 18 19import ( 20 "encoding/asn1" 21 "encoding/hex" 22 "math/big" 23 "testing" 24 25 "github.com/google/tink/go/signature/subtle" 26 "github.com/google/tink/go/subtle/random" 27) 28 29type paramsTestECDSA struct { 30 hash string 31 curve string 32 encoding string 33} 34 35func TestECDSAEncodeDecodeDER(t *testing.T) { 36 nTest := 1000 37 for i := 0; i < nTest; i++ { 38 sig := newECDSARandomSignature() 39 encoding := "DER" 40 encoded, err := sig.EncodeECDSASignature(encoding, "P-256") 41 if err != nil { 42 t.Errorf("unexpected error during encoding: %s", err) 43 } 44 // first byte is 0x30 45 if encoded[0] != byte(0x30) { 46 t.Errorf("first byte is incorrect, expected 48, got %v", encoded[0]) 47 } 48 // tag is 2 49 if encoded[2] != byte(2) || encoded[4+encoded[3]] != byte(2) { 50 t.Errorf("expect tag to be 2 (integer), got %d and %d", encoded[2], encoded[4+encoded[3]]) 51 } 52 // length 53 if len(encoded) != int(encoded[1])+2 { 54 t.Errorf("incorrect length, expected %d, got %d", len(encoded), encoded[1]+2) 55 } 56 decodedSig, err := subtle.DecodeECDSASignature(encoded, encoding) 57 if err != nil { 58 t.Errorf("unexpected error during decoding: %s", err) 59 } 60 if decodedSig.R.Cmp(sig.R) != 0 || decodedSig.S.Cmp(sig.S) != 0 { 61 t.Errorf("decoded signature doesn't match original value") 62 } 63 } 64} 65 66func TestECDSAEncodeDecodeIEEEP1363(t *testing.T) { 67 nTest := 1000 68 for i := 0; i < nTest; i++ { 69 sig := newECDSARandomSignature() 70 encoding := "IEEE_P1363" 71 encoded, err := sig.EncodeECDSASignature(encoding, "P-256") 72 if err != nil { 73 t.Errorf("unexpected error during encoding: %s", err) 74 } 75 if len(encoded) != 64 { 76 t.Errorf("incorrect length, expected %d, got %d", 64, len(encoded)) 77 } 78 if len(sig.R.Bytes()) < 32 { 79 expectedZeros := 32 - len(sig.R.Bytes()) 80 for i := 0; i < expectedZeros; i++ { 81 if encoded[i] != 0 { 82 t.Errorf("expect byte %d to be 0, got %d. encoded data = %s", i, encoded[i], hex.Dump(encoded)) 83 } 84 } 85 } 86 if len(sig.S.Bytes()) < 32 { 87 expectedZeros := 32 - len(sig.S.Bytes()) 88 for i := 32; i < (32 + expectedZeros); i++ { 89 if encoded[i] != 0 { 90 t.Errorf("expect byte %d to be 0, got %d. encoded data = %s", i, encoded[i], hex.Dump(encoded)) 91 } 92 } 93 } 94 decodedSig, err := subtle.DecodeECDSASignature(encoded, encoding) 95 if err != nil { 96 t.Errorf("unexpected error during decoding: %s", err) 97 } 98 if decodedSig.R.Cmp(sig.R) != 0 || decodedSig.S.Cmp(sig.S) != 0 { 99 t.Errorf("decoded signature doesn't match original value") 100 } 101 } 102} 103 104func TestECDSAEncodeWithInvalidInput(t *testing.T) { 105 sig := newECDSARandomSignature() 106 _, err := sig.EncodeECDSASignature("UNKNOWN_ENCODING", "P-256") 107 if err == nil { 108 t.Errorf("expect an error when encoding is invalid") 109 } 110} 111 112func TestECDSADecodeWithInvalidInput(t *testing.T) { 113 var sig *subtle.ECDSASignature 114 var encoded []byte 115 encoding := "DER" 116 117 // modified first byte 118 sig = newECDSARandomSignature() 119 encoded, _ = sig.EncodeECDSASignature(encoding, "P-256") 120 encoded[0] = 0x31 121 if _, err := subtle.DecodeECDSASignature(encoded, encoding); err == nil { 122 t.Errorf("expect an error when first byte is not 0x30") 123 } 124 // modified tag 125 sig = newECDSARandomSignature() 126 encoded, _ = sig.EncodeECDSASignature(encoding, "P-256") 127 encoded[2] = encoded[2] + 1 128 if _, err := subtle.DecodeECDSASignature(encoded, encoding); err == nil { 129 t.Errorf("expect an error when tag is modified") 130 } 131 // modified length 132 sig = newECDSARandomSignature() 133 encoded, _ = sig.EncodeECDSASignature(encoding, "P-256") 134 encoded[1] = encoded[1] + 1 135 if _, err := subtle.DecodeECDSASignature(encoded, encoding); err == nil { 136 t.Errorf("expect an error when length is modified") 137 } 138 // append unused 0s 139 sig = newECDSARandomSignature() 140 encoded, _ = sig.EncodeECDSASignature(encoding, "P-256") 141 tmp := make([]byte, len(encoded)+4) 142 copy(tmp, encoded) 143 if _, err := subtle.DecodeECDSASignature(tmp, encoding); err == nil { 144 t.Errorf("expect an error when unused 0s are appended to signature") 145 } 146 // a struct with three numbers 147 randomStruct := struct{ X, Y, Z *big.Int }{ 148 X: new(big.Int).SetBytes(random.GetRandomBytes(32)), 149 Y: new(big.Int).SetBytes(random.GetRandomBytes(32)), 150 Z: new(big.Int).SetBytes(random.GetRandomBytes(32)), 151 } 152 encoded, _ = asn1.Marshal(randomStruct) 153 if _, err := subtle.DecodeECDSASignature(encoded, encoding); err == nil { 154 t.Errorf("expect an error when input is not an ECDSASignature") 155 } 156} 157 158func TestECDSAValidateParams(t *testing.T) { 159 params := genECDSAValidParams() 160 for i := 0; i < len(params); i++ { 161 if err := subtle.ValidateECDSAParams(params[i].hash, params[i].curve, params[i].encoding); err != nil { 162 t.Errorf("unexpected error for valid params: %s, i = %d", err, i) 163 } 164 } 165 params = genECDSAInvalidParams() 166 for i := 0; i < len(params); i++ { 167 if err := subtle.ValidateECDSAParams(params[i].hash, params[i].curve, params[i].encoding); err == nil { 168 t.Errorf("expect an error when params are invalid, i = %d", i) 169 } 170 } 171} 172 173func genECDSAInvalidParams() []paramsTestECDSA { 174 encodings := []string{"DER", "IEEE_P1363"} 175 testCases := []paramsTestECDSA{ 176 // invalid encoding 177 {hash: "SHA256", curve: "NIST_P256", encoding: "UNKNOWN_ENCODING"}, 178 // invalid hash 179 {hash: "SHA1", curve: "NIST_P256", encoding: "IEEE_P1363"}, 180 // invalid curve 181 {hash: "SHA1", curve: "UNKNOWN_CURVE", encoding: "IEEE_P1363"}, 182 } 183 for _, encoding := range encodings { 184 testCases = append(testCases, 185 // invalid curve 186 paramsTestECDSA{hash: "SHA256", curve: "UNKNOWN_CURVE", encoding: encoding}, 187 // invalid hash: P256 and SHA-512 188 paramsTestECDSA{hash: "SHA512", curve: "NIST_P256", encoding: encoding}, 189 // invalid hash: P521 and SHA-256 190 paramsTestECDSA{hash: "SHA256", curve: "NIST_P521", encoding: encoding}, 191 // invalid hash: P384 and SHA-256 192 paramsTestECDSA{hash: "SHA256", curve: "NIST_P384", encoding: encoding}, 193 ) 194 } 195 return testCases 196} 197 198func genECDSAValidParams() []paramsTestECDSA { 199 return []paramsTestECDSA{ 200 {hash: "SHA256", curve: "NIST_P256", encoding: "DER"}, 201 {hash: "SHA256", curve: "NIST_P256", encoding: "IEEE_P1363"}, 202 {hash: "SHA384", curve: "NIST_P384", encoding: "DER"}, 203 {hash: "SHA384", curve: "NIST_P384", encoding: "IEEE_P1363"}, 204 {hash: "SHA512", curve: "NIST_P384", encoding: "DER"}, 205 {hash: "SHA512", curve: "NIST_P384", encoding: "IEEE_P1363"}, 206 {hash: "SHA512", curve: "NIST_P521", encoding: "DER"}, 207 {hash: "SHA512", curve: "NIST_P521", encoding: "IEEE_P1363"}, 208 } 209} 210 211func newECDSARandomSignature() *subtle.ECDSASignature { 212 r := new(big.Int).SetBytes(random.GetRandomBytes(32)) 213 s := new(big.Int).SetBytes(random.GetRandomBytes(32)) 214 return subtle.NewECDSASignature(r, s) 215} 216