xref: /aosp_15_r20/external/tink/go/signature/subtle/encoding.go (revision e7b1675dde1b92d52ec075b0a92829627f2c52a5)
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	"bytes"
21	"crypto/elliptic"
22	"encoding/asn1"
23	"fmt"
24	"math/big"
25)
26
27// asn1encode encodes the given ECDSA signature using ASN.1 encoding.
28func asn1encode(sig *ECDSASignature) ([]byte, error) {
29	ret, err := asn1.Marshal(*sig)
30	if err != nil {
31		return nil, fmt.Errorf("asn.1 encoding failed")
32	}
33	return ret, nil
34}
35
36var errAsn1Decoding = fmt.Errorf("asn.1 decoding failed")
37
38// asn1decode verifies the given ECDSA signature and decodes it if it is valid.
39// Since asn1.Unmarshal() doesn't do a strict verification on its input, it will
40// accept signatures with trailing data. Thus, we add an additional check to make sure
41// that the input follows strict DER encoding: after unmarshalling the signature bytes,
42// we marshal the obtained signature object again. Since DER encoding is deterministic,
43// we expect that the obtained bytes would be equal to the input.
44func asn1decode(b []byte) (*ECDSASignature, error) {
45	// parse the signature
46	sig := new(ECDSASignature)
47	_, err := asn1.Unmarshal(b, sig)
48	if err != nil {
49		return nil, errAsn1Decoding
50	}
51	// encode the signature again
52	encoded, err := asn1.Marshal(*sig)
53	if err != nil {
54		return nil, errAsn1Decoding
55	}
56	if !bytes.Equal(b, encoded) {
57		return nil, errAsn1Decoding
58	}
59	return sig, nil
60}
61
62func ieeeSignatureSize(curveName string) (int, error) {
63	switch curveName {
64	case elliptic.P256().Params().Name:
65		return 64, nil
66	case elliptic.P384().Params().Name:
67		return 96, nil
68	case elliptic.P521().Params().Name:
69		return 132, nil
70	default:
71		return 0, fmt.Errorf("ieeeP1363 unsupported curve name: %q", curveName)
72	}
73}
74
75func ieeeP1363Encode(sig *ECDSASignature, curveName string) ([]byte, error) {
76	sigSize, err := ieeeSignatureSize(curveName)
77	if err != nil {
78		return nil, err
79	}
80
81	enc := make([]byte, sigSize)
82
83	// sigR and sigS must be half the size of the signature. If not, we need to pad them with zeros.
84	offset := 0
85	if len(sig.R.Bytes()) < (sigSize / 2) {
86		offset += (sigSize / 2) - len(sig.R.Bytes())
87	}
88	// Copy sigR after any zero-padding.
89	copy(enc[offset:], sig.R.Bytes())
90
91	// Skip the bytes of sigR.
92	offset = sigSize / 2
93	if len(sig.S.Bytes()) < (sigSize / 2) {
94		offset += (sigSize / 2) - len(sig.S.Bytes())
95	}
96	// Copy sigS after sigR and any zero-padding.
97	copy(enc[offset:], sig.S.Bytes())
98
99	return enc, nil
100}
101
102func ieeeP1363Decode(encodedBytes []byte) (*ECDSASignature, error) {
103	if len(encodedBytes) == 0 || len(encodedBytes) > 132 || len(encodedBytes)%2 != 0 {
104		return nil, fmt.Errorf("ecdsa: Invalid IEEE_P1363 encoded bytes")
105	}
106	r := new(big.Int).SetBytes(encodedBytes[:len(encodedBytes)/2])
107	s := new(big.Int).SetBytes(encodedBytes[len(encodedBytes)/2:])
108	return &ECDSASignature{R: r, S: s}, nil
109}
110