1 /**********************************************************************
2  * Copyright (c) 2015 Pieter Wuille                                   *
3  * Distributed under the MIT software license, see the accompanying   *
4  * file COPYING or http://www.opensource.org/licenses/mit-license.php.*
5  **********************************************************************/
6 
7 #include <string.h>
8 #include <secp256k1.h>
9 
10 #include "lax_der_parsing.h"
11 
ecdsa_signature_parse_der_lax(const secp256k1_context * ctx,secp256k1_ecdsa_signature * sig,const unsigned char * input,size_t inputlen)12 int ecdsa_signature_parse_der_lax(const secp256k1_context* ctx, secp256k1_ecdsa_signature* sig, const unsigned char *input, size_t inputlen) {
13     size_t rpos, rlen, spos, slen;
14     size_t pos = 0;
15     size_t lenbyte;
16     unsigned char tmpsig[64] = {0};
17     int overflow = 0;
18 
19     /* Hack to initialize sig with a correctly-parsed but invalid signature. */
20     secp256k1_ecdsa_signature_parse_compact(ctx, sig, tmpsig);
21 
22     /* Sequence tag byte */
23     if (pos == inputlen || input[pos] != 0x30) {
24         return 0;
25     }
26     pos++;
27 
28     /* Sequence length bytes */
29     if (pos == inputlen) {
30         return 0;
31     }
32     lenbyte = input[pos++];
33     if (lenbyte & 0x80) {
34         lenbyte -= 0x80;
35         if (pos + lenbyte > inputlen) {
36             return 0;
37         }
38         pos += lenbyte;
39     }
40 
41     /* Integer tag byte for R */
42     if (pos == inputlen || input[pos] != 0x02) {
43         return 0;
44     }
45     pos++;
46 
47     /* Integer length for R */
48     if (pos == inputlen) {
49         return 0;
50     }
51     lenbyte = input[pos++];
52     if (lenbyte & 0x80) {
53         lenbyte -= 0x80;
54         if (pos + lenbyte > inputlen) {
55             return 0;
56         }
57         while (lenbyte > 0 && input[pos] == 0) {
58             pos++;
59             lenbyte--;
60         }
61         if (lenbyte >= sizeof(size_t)) {
62             return 0;
63         }
64         rlen = 0;
65         while (lenbyte > 0) {
66             rlen = (rlen << 8) + input[pos];
67             pos++;
68             lenbyte--;
69         }
70     } else {
71         rlen = lenbyte;
72     }
73     if (rlen > inputlen - pos) {
74         return 0;
75     }
76     rpos = pos;
77     pos += rlen;
78 
79     /* Integer tag byte for S */
80     if (pos == inputlen || input[pos] != 0x02) {
81         return 0;
82     }
83     pos++;
84 
85     /* Integer length for S */
86     if (pos == inputlen) {
87         return 0;
88     }
89     lenbyte = input[pos++];
90     if (lenbyte & 0x80) {
91         lenbyte -= 0x80;
92         if (pos + lenbyte > inputlen) {
93             return 0;
94         }
95         while (lenbyte > 0 && input[pos] == 0) {
96             pos++;
97             lenbyte--;
98         }
99         if (lenbyte >= sizeof(size_t)) {
100             return 0;
101         }
102         slen = 0;
103         while (lenbyte > 0) {
104             slen = (slen << 8) + input[pos];
105             pos++;
106             lenbyte--;
107         }
108     } else {
109         slen = lenbyte;
110     }
111     if (slen > inputlen - pos) {
112         return 0;
113     }
114     spos = pos;
115     pos += slen;
116 
117     /* Ignore leading zeroes in R */
118     while (rlen > 0 && input[rpos] == 0) {
119         rlen--;
120         rpos++;
121     }
122     /* Copy R value */
123     if (rlen > 32) {
124         overflow = 1;
125     } else {
126         memcpy(tmpsig + 32 - rlen, input + rpos, rlen);
127     }
128 
129     /* Ignore leading zeroes in S */
130     while (slen > 0 && input[spos] == 0) {
131         slen--;
132         spos++;
133     }
134     /* Copy S value */
135     if (slen > 32) {
136         overflow = 1;
137     } else {
138         memcpy(tmpsig + 64 - slen, input + spos, slen);
139     }
140 
141     if (!overflow) {
142         overflow = !secp256k1_ecdsa_signature_parse_compact(ctx, sig, tmpsig);
143     }
144     if (overflow) {
145         memset(tmpsig, 0, 64);
146         secp256k1_ecdsa_signature_parse_compact(ctx, sig, tmpsig);
147     }
148     return 1;
149 }
150 
151