1 /*-
2  * Copyright (c) 2018 Ribose Inc.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
15  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
16  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
18  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
19  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
20  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
21  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
22  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
23  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
24  * POSSIBILITY OF SUCH DAMAGE.
25  */
26 
27 #include <string.h>
28 #include <stdlib.h>
29 #include "mpi.h"
30 #include "hash.h"
31 #include "mem.h"
32 #include "utils.h"
33 
34 bignum_t *
mpi2bn(const pgp_mpi_t * val)35 mpi2bn(const pgp_mpi_t *val)
36 {
37     return bn_bin2bn(val->mpi, val->len, NULL);
38 }
39 
40 bool
bn2mpi(bignum_t * bn,pgp_mpi_t * val)41 bn2mpi(bignum_t *bn, pgp_mpi_t *val)
42 {
43     return bn_num_bytes(bn, &val->len) && (bn_bn2bin(bn, val->mpi) == 0);
44 }
45 
46 size_t
mpi_bits(const pgp_mpi_t * val)47 mpi_bits(const pgp_mpi_t *val)
48 {
49     size_t  bits = 0;
50     size_t  idx = 0;
51     uint8_t bt;
52 
53     for (idx = 0; (idx < val->len) && !val->mpi[idx]; idx++)
54         ;
55 
56     if (idx < val->len) {
57         for (bits = (val->len - idx - 1) << 3, bt = val->mpi[idx]; bt; bits++, bt = bt >> 1)
58             ;
59     }
60 
61     return bits;
62 }
63 
64 size_t
mpi_bytes(const pgp_mpi_t * val)65 mpi_bytes(const pgp_mpi_t *val)
66 {
67     return val->len;
68 }
69 
70 bool
mem2mpi(pgp_mpi_t * val,const void * mem,size_t len)71 mem2mpi(pgp_mpi_t *val, const void *mem, size_t len)
72 {
73     if (len > sizeof(val->mpi)) {
74         return false;
75     }
76 
77     memcpy(val->mpi, mem, len);
78     val->len = len;
79     return true;
80 }
81 
82 void
mpi2mem(const pgp_mpi_t * val,void * mem)83 mpi2mem(const pgp_mpi_t *val, void *mem)
84 {
85     memcpy(mem, val->mpi, val->len);
86 }
87 
88 char *
mpi2hex(const pgp_mpi_t * val)89 mpi2hex(const pgp_mpi_t *val)
90 {
91     static const char *hexes = "0123456789abcdef";
92     char *             out;
93     size_t             len;
94     size_t             idx = 0;
95 
96     len = mpi_bytes(val);
97     out = (char *) malloc(len * 2 + 1);
98 
99     if (!out) {
100         return out;
101     }
102 
103     for (size_t i = 0; i < len; i++) {
104         out[idx++] = hexes[val->mpi[i] >> 4];
105         out[idx++] = hexes[val->mpi[i] & 0xf];
106     }
107     out[idx] = '\0';
108     return out;
109 }
110 
111 bool
mpi_equal(const pgp_mpi_t * val1,const pgp_mpi_t * val2)112 mpi_equal(const pgp_mpi_t *val1, const pgp_mpi_t *val2)
113 {
114     size_t idx1 = 0;
115     size_t idx2 = 0;
116 
117     for (idx1 = 0; (idx1 < val1->len) && !val1->mpi[idx1]; idx1++)
118         ;
119 
120     for (idx2 = 0; (idx2 < val2->len) && !val2->mpi[idx2]; idx2++)
121         ;
122 
123     return ((val1->len - idx1) == (val2->len - idx2) &&
124             !memcmp(val1->mpi + idx1, val2->mpi + idx2, val1->len - idx1));
125 }
126 
127 /* hashes 32-bit length + mpi body (paddded with 0 if high order byte is >= 0x80) */
128 bool
mpi_hash(const pgp_mpi_t * val,pgp_hash_t * hash)129 mpi_hash(const pgp_mpi_t *val, pgp_hash_t *hash)
130 {
131     size_t  len;
132     size_t  idx;
133     uint8_t padbyte = 0;
134     bool    res = true;
135 
136     len = mpi_bytes(val);
137     for (idx = 0; (idx < len) && (val->mpi[idx] == 0); idx++)
138         ;
139 
140     if (idx >= len) {
141         return pgp_hash_uint32(hash, 0);
142     }
143 
144     res = pgp_hash_uint32(hash, len - idx);
145     if (val->mpi[idx] & 0x80) {
146         res &= pgp_hash_add(hash, &padbyte, 1);
147     }
148     res &= pgp_hash_add(hash, val->mpi + idx, len - idx);
149 
150     return res;
151 }
152 
153 void
mpi_forget(pgp_mpi_t * val)154 mpi_forget(pgp_mpi_t *val)
155 {
156     secure_clear(val, sizeof(*val));
157     val->len = 0;
158 }
159