File Coverage

src/ec/ecdsa_rta.c
Criterion Covered Total %
statement 31 40 77.5
branch 10 20 50.0
condition n/a
subroutine n/a
pod n/a
total 41 60 68.3


line stmt bran cond sub pod time code
1             /*
2             * Copyright (c) 2016 Thomas Pornin
3             *
4             * Permission is hereby granted, free of charge, to any person obtaining
5             * a copy of this software and associated documentation files (the
6             * "Software"), to deal in the Software without restriction, including
7             * without limitation the rights to use, copy, modify, merge, publish,
8             * distribute, sublicense, and/or sell copies of the Software, and to
9             * permit persons to whom the Software is furnished to do so, subject to
10             * the following conditions:
11             *
12             * The above copyright notice and this permission notice shall be
13             * included in all copies or substantial portions of the Software.
14             *
15             * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16             * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17             * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18             * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
19             * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
20             * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21             * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22             * SOFTWARE.
23             */
24              
25             #include "inner.h"
26              
27             /*
28             * Compute ASN.1 encoded length for the provided integer. The ASN.1
29             * encoding is signed, so its leading bit must have value 0; it must
30             * also be of minimal length (so leading bytes of value 0 must be
31             * removed, except if that would contradict the rule about the sign
32             * bit).
33             */
34             static size_t
35 2           asn1_int_length(const unsigned char *x, size_t xlen)
36             {
37 2 50         while (xlen > 0 && *x == 0) {
    50          
38 0           x ++;
39 0           xlen --;
40             }
41 2 50         if (xlen == 0 || *x >= 0x80) {
    50          
42 2           xlen ++;
43             }
44 2           return xlen;
45             }
46              
47             /* see bearssl_ec.h */
48             size_t
49 1           br_ecdsa_raw_to_asn1(void *sig, size_t sig_len)
50             {
51             /*
52             * Internal buffer is large enough to accommodate a signature
53             * such that r and s fit on 125 bytes each (signed encoding),
54             * meaning a curve order of up to 999 bits. This is the limit
55             * that ensures "simple" length encodings.
56             */
57             unsigned char *buf;
58             size_t hlen, rlen, slen, zlen, off;
59             unsigned char tmp[257];
60              
61 1           buf = sig;
62 1 50         if ((sig_len & 1) != 0) {
63 0           return 0;
64             }
65              
66             /*
67             * Compute lengths for the two integers.
68             */
69 1           hlen = sig_len >> 1;
70 1           rlen = asn1_int_length(buf, hlen);
71 1           slen = asn1_int_length(buf + hlen, hlen);
72 1 50         if (rlen > 125 || slen > 125) {
    50          
73 0           return 0;
74             }
75              
76             /*
77             * SEQUENCE header.
78             */
79 1           tmp[0] = 0x30;
80 1           zlen = rlen + slen + 4;
81 1 50         if (zlen >= 0x80) {
82 0           tmp[1] = 0x81;
83 0           tmp[2] = zlen;
84 0           off = 3;
85             } else {
86 1           tmp[1] = zlen;
87 1           off = 2;
88             }
89              
90             /*
91             * First INTEGER (r).
92             */
93 1           tmp[off ++] = 0x02;
94 1           tmp[off ++] = rlen;
95 1 50         if (rlen > hlen) {
96 1           tmp[off] = 0x00;
97 1           memcpy(tmp + off + 1, buf, hlen);
98             } else {
99 0           memcpy(tmp + off, buf + hlen - rlen, rlen);
100             }
101 1           off += rlen;
102              
103             /*
104             * Second INTEGER (s).
105             */
106 1           tmp[off ++] = 0x02;
107 1           tmp[off ++] = slen;
108 1 50         if (slen > hlen) {
109 1           tmp[off] = 0x00;
110 1           memcpy(tmp + off + 1, buf + hlen, hlen);
111             } else {
112 0           memcpy(tmp + off, buf + sig_len - slen, slen);
113             }
114 1           off += slen;
115              
116             /*
117             * Return ASN.1 signature.
118             */
119 1           memcpy(sig, tmp, off);
120 1           return off;
121             }