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 (lenbyte > inputlen - pos) {
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 (lenbyte > inputlen - pos) {
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 (lenbyte > inputlen - pos) {
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 
116     /* Ignore leading zeroes in R */
117     while (rlen > 0 && input[rpos] == 0) {
118         rlen--;
119         rpos++;
120     }
121     /* Copy R value */
122     if (rlen > 32) {
123         overflow = 1;
124     } else {
125         memcpy(tmpsig + 32 - rlen, input + rpos, rlen);
126     }
127 
128     /* Ignore leading zeroes in S */
129     while (slen > 0 && input[spos] == 0) {
130         slen--;
131         spos++;
132     }
133     /* Copy S value */
134     if (slen > 32) {
135         overflow = 1;
136     } else {
137         memcpy(tmpsig + 64 - slen, input + spos, slen);
138     }
139 
140     if (!overflow) {
141         overflow = !secp256k1_ecdsa_signature_parse_compact(ctx, sig, tmpsig);
142     }
143     if (overflow) {
144         memset(tmpsig, 0, 64);
145         secp256k1_ecdsa_signature_parse_compact(ctx, sig, tmpsig);
146     }
147     return 1;
148 }
149 
150