1 /*
2 * Copyright 2014-2022 The GmSSL Project. All Rights Reserved.
3 *
4 * Licensed under the Apache License, Version 2.0 (the License); you may
5 * not use this file except in compliance with the License.
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 */
9
10
11
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <string.h>
15 #include <stdint.h>
16 #include <gmssl/error.h>
17
OPENSSL_hexchar2int(unsigned char c)18 int OPENSSL_hexchar2int(unsigned char c)
19 {
20 switch (c) {
21 case '0':
22 return 0;
23 case '1':
24 return 1;
25 case '2':
26 return 2;
27 case '3':
28 return 3;
29 case '4':
30 return 4;
31 case '5':
32 return 5;
33 case '6':
34 return 6;
35 case '7':
36 return 7;
37 case '8':
38 return 8;
39 case '9':
40 return 9;
41 case 'a':
42 case 'A':
43 return 0x0A;
44 case 'b': case 'B':
45 return 0x0B;
46 case 'c': case 'C':
47 return 0x0C;
48 case 'd': case 'D':
49 return 0x0D;
50 case 'e': case 'E':
51 return 0x0E;
52 case 'f': case 'F':
53 return 0x0F;
54 }
55 return -1;
56 }
57
OPENSSL_hexstr2buf(const char * str,size_t * len)58 unsigned char *OPENSSL_hexstr2buf(const char *str, size_t *len)
59 {
60 unsigned char *hexbuf, *q;
61 unsigned char ch, cl;
62 int chi, cli;
63 const unsigned char *p;
64 size_t s;
65
66 s = strlen(str);
67 if ((hexbuf = malloc(s >> 1)) == NULL) {
68 return NULL;
69 }
70 for (p = (const unsigned char *)str, q = hexbuf; *p; ) {
71 ch = *p++;
72 if (ch == ':')
73 continue;
74 cl = *p++;
75 if (!cl) {
76 //CRYPTOerr(CRYPTO_F_OPENSSL_HEXSTR2BUF, CRYPTO_R_ODD_NUMBER_OF_DIGITS);
77 free(hexbuf);
78 return NULL;
79 }
80 cli = OPENSSL_hexchar2int(cl);
81 chi = OPENSSL_hexchar2int(ch);
82 if (cli < 0 || chi < 0) {
83 free(hexbuf);
84 //CRYPTOerr(CRYPTO_F_OPENSSL_HEXSTR2BUF, CRYPTO_R_ILLEGAL_HEX_DIGIT);
85 return NULL;
86 }
87 *q++ = (unsigned char)((chi << 4) | cli);
88 }
89
90 if (len)
91 *len = q - hexbuf;
92 return hexbuf;
93 }
94
95
hexchar2int(char c)96 static int hexchar2int(char c)
97 {
98 if ('0' <= c && c <= '9') return c - '0';
99 else if ('a' <= c && c <= 'f') return c - 'a' + 10;
100 else if ('A' <= c && c <= 'F') return c - 'A' + 10;
101 else return -1;
102 }
103
hex2bin(const char * in,size_t inlen,uint8_t * out)104 int hex2bin(const char *in, size_t inlen, uint8_t *out)
105 {
106 int c;
107 if (inlen % 2) {
108 error_print_msg("hex %s len = %zu\n", in, inlen);
109 return -1;
110 }
111
112 while (inlen) {
113 if ((c = hexchar2int(*in++)) < 0) {
114 error_print_msg("%d", 5);
115 return -1;
116 }
117 *out = (uint8_t)c << 4;
118 if ((c = hexchar2int(*in++)) < 0) {
119 error_print();
120 return -1;
121 }
122 *out |= (uint8_t)c;
123 inlen -= 2;
124 out++;
125 }
126 return 1;
127 }
128
hex_to_bytes(const char * in,size_t inlen,uint8_t * out,size_t * outlen)129 int hex_to_bytes(const char *in, size_t inlen, uint8_t *out, size_t *outlen)
130 {
131 *outlen = inlen/2;
132 return hex2bin(in, inlen, out);
133 }
134
135
memxor(void * r,const void * a,size_t len)136 void memxor(void *r, const void *a, size_t len)
137 {
138 uint8_t *pr = r;
139 const uint8_t *pa = a;
140 size_t i;
141 for (i = 0; i < len; i++) {
142 pr[i] ^= pa[i];
143 }
144
145 }
146
147
gmssl_memxor(void * r,const void * a,const void * b,size_t len)148 void gmssl_memxor(void *r, const void *a, const void *b, size_t len)
149 {
150 uint8_t *pr = r;
151 const uint8_t *pa = a;
152 const uint8_t *pb = b;
153 size_t i;
154 for (i = 0; i < len; i++) {
155 pr[i] = pa[i] ^ pb[i];
156 }
157 }
158
159
160 // Note: comments and code from OpenSSL crypto/cryptlib.c:CRYPTO_memcmp()
161 /* volatile unsigned char* pointers are there because
162 * 1. Accessing a variable declared volatile via a pointer
163 * that lacks a volatile qualifier causes undefined behavior.
164 * 2. When the variable itself is not volatile the compiler is
165 * not required to keep all those reads and can convert
166 * this into canonical memcmp() which doesn't read the whole block.
167 * Pointers to volatile resolve the first problem fully. The second
168 * problem cannot be resolved in any Standard-compliant way but this
169 * works the problem around. Compilers typically react to
170 * pointers to volatile by preserving the reads and writes through them.
171 * The latter is not required by the Standard if the memory pointed to
172 * is not volatile.
173 * Pointers themselves are volatile in the function signature to work
174 * around a subtle bug in gcc 4.6+ which causes writes through
175 * pointers to volatile to not be emitted in some rare,
176 * never needed in real life, pieces of code.
177 */
gmssl_secure_memcmp(const volatile void * volatile in_a,const volatile void * volatile in_b,size_t len)178 int gmssl_secure_memcmp(const volatile void * volatile in_a, const volatile void * volatile in_b, size_t len)
179 {
180 size_t i;
181 const volatile unsigned char *a = in_a;
182 const volatile unsigned char *b = in_b;
183 unsigned char x = 0;
184
185 for (i = 0; i < len; i++) {
186 x |= a[i] ^ b[i];
187 }
188
189 return x;
190 }
191
192 /*
193 * Pointer to memset is volatile so that compiler must de-reference
194 * the pointer and can't assume that it points to any function in
195 * particular (such as memset, which it then might further "optimize")
196 */
197 typedef void *(*memset_t)(void *, int, size_t);
198
199 static volatile memset_t memset_func = memset;
200
gmssl_secure_clear(void * ptr,size_t len)201 void gmssl_secure_clear(void *ptr, size_t len)
202 {
203 memset_func(ptr, 0, len);
204 }
205
mem_is_zero(const uint8_t * buf,size_t len)206 int mem_is_zero(const uint8_t *buf, size_t len)
207 {
208 int ret = 1;
209 size_t i;
210 for (i = 0; i < len; i++) {
211 if (buf[i]) ret = 0;
212 }
213 return ret;
214 }
215
216
217
218
219
220