Skip to content

Commit f989765

Browse files
committed
Split out ASN.1 to new files
1 parent 78e1f2e commit f989765

File tree

4 files changed

+444
-387
lines changed

4 files changed

+444
-387
lines changed

src/utility/ASN1Utils.cpp

Lines changed: 349 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,349 @@
1+
/*
2+
This file is part of the ArduinoECCX08 library.
3+
Copyright (c) 2019 Arduino SA. All rights reserved.
4+
5+
This library is free software; you can redistribute it and/or
6+
modify it under the terms of the GNU Lesser General Public
7+
License as published by the Free Software Foundation; either
8+
version 2.1 of the License, or (at your option) any later version.
9+
10+
This library is distributed in the hope that it will be useful,
11+
but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13+
Lesser General Public License for more details.
14+
15+
You should have received a copy of the GNU Lesser General Public
16+
License along with this library; if not, write to the Free Software
17+
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18+
*/
19+
20+
#include "ASN1Utils.h"
21+
22+
int ASN1UtilsClass::versionLength()
23+
{
24+
return 3;
25+
}
26+
27+
int ASN1UtilsClass::subjectLength(const String& countryName,
28+
const String& stateProvinceName,
29+
const String& localityName,
30+
const String& organizationName,
31+
const String& organizationalUnitName,
32+
const String& commonName)
33+
{
34+
int length = 0;
35+
int countryNameLength = countryName.length();
36+
int stateProvinceNameLength = stateProvinceName.length();
37+
int localityNameLength = localityName.length();
38+
int organizationNameLength = organizationName.length();
39+
int organizationalUnitNameLength = organizationalUnitName.length();
40+
int commonNameLength = commonName.length();
41+
42+
if (countryNameLength) {
43+
length += (11 + countryNameLength);
44+
}
45+
46+
if (stateProvinceNameLength) {
47+
length += (11 + stateProvinceNameLength);
48+
}
49+
50+
if (localityNameLength) {
51+
length += (11 + localityNameLength);
52+
}
53+
54+
if (organizationNameLength) {
55+
length += (11 + organizationNameLength);
56+
}
57+
58+
if (organizationalUnitNameLength) {
59+
length += (11 + organizationalUnitNameLength);
60+
}
61+
62+
if (commonNameLength) {
63+
length += (11 + commonNameLength);
64+
}
65+
66+
return length;
67+
}
68+
69+
int ASN1UtilsClass::publicKeyLength()
70+
{
71+
return (2 + 2 + 9 + 10 + 4 + 64);
72+
}
73+
74+
int ASN1UtilsClass::signatureLength(const byte signature[])
75+
{
76+
const byte* r = &signature[0];
77+
const byte* s = &signature[32];
78+
79+
int rLength = 32;
80+
int sLength = 32;
81+
82+
while (*r == 0x00 && rLength) {
83+
r++;
84+
rLength--;
85+
}
86+
87+
if (*r & 0x80) {
88+
rLength++;
89+
}
90+
91+
while (*s == 0x00 && sLength) {
92+
s++;
93+
sLength--;
94+
}
95+
96+
if (*s & 0x80) {
97+
sLength++;
98+
}
99+
100+
return (21 + rLength + sLength);
101+
}
102+
103+
int ASN1UtilsClass::sequenceHeaderLength(int length)
104+
{
105+
if (length > 255) {
106+
return 4;
107+
} else if (length > 127) {
108+
return 3;
109+
} else {
110+
return 2;
111+
}
112+
}
113+
114+
void ASN1UtilsClass::appendVersion(int version, byte out[])
115+
{
116+
out[0] = ASN1_INTEGER;
117+
out[1] = 0x01;
118+
out[2] = version;
119+
}
120+
121+
void ASN1UtilsClass::appendSubject(const String& countryName,
122+
const String& stateProvinceName,
123+
const String& localityName,
124+
const String& organizationName,
125+
const String& organizationalUnitName,
126+
const String& commonName,
127+
byte out[])
128+
{
129+
if (countryName.length() > 0) {
130+
out += appendName(countryName, 0x06, out);
131+
}
132+
133+
if (stateProvinceName.length() > 0) {
134+
out += appendName(stateProvinceName, 0x08, out);
135+
}
136+
137+
if (localityName.length() > 0) {
138+
out += appendName(localityName, 0x07, out);
139+
}
140+
141+
if (organizationName.length() > 0) {
142+
out += appendName(organizationName, 0x0a, out);
143+
}
144+
145+
if (organizationalUnitName.length() > 0) {
146+
out += appendName(organizationalUnitName, 0x0b, out);
147+
}
148+
149+
if (commonName.length() > 0) {
150+
out += appendName(commonName, 0x03, out);
151+
}
152+
}
153+
154+
void ASN1UtilsClass::appendPublicKey(const byte publicKey[], byte out[])
155+
{
156+
int subjectPublicKeyDataLength = 2 + 9 + 10 + 4 + 64;
157+
158+
// subject public key
159+
*out++ = ASN1_SEQUENCE;
160+
*out++ = (subjectPublicKeyDataLength) & 0xff;
161+
162+
*out++ = ASN1_SEQUENCE;
163+
*out++ = 0x13;
164+
165+
// EC public key
166+
*out++ = ASN1_OBJECT_IDENTIFIER;
167+
*out++ = 0x07;
168+
*out++ = 0x2a;
169+
*out++ = 0x86;
170+
*out++ = 0x48;
171+
*out++ = 0xce;
172+
*out++ = 0x3d;
173+
*out++ = 0x02;
174+
*out++ = 0x01;
175+
176+
// PRIME 256 v1
177+
*out++ = ASN1_OBJECT_IDENTIFIER;
178+
*out++ = 0x08;
179+
*out++ = 0x2a;
180+
*out++ = 0x86;
181+
*out++ = 0x48;
182+
*out++ = 0xce;
183+
*out++ = 0x3d;
184+
*out++ = 0x03;
185+
*out++ = 0x01;
186+
*out++ = 0x07;
187+
188+
*out++ = 0x03;
189+
*out++ = 0x42;
190+
*out++ = 0x00;
191+
*out++ = 0x04;
192+
193+
memcpy(out, publicKey, 64);
194+
}
195+
196+
void ASN1UtilsClass::appendSignature(const byte signature[], byte out[])
197+
{
198+
// signature algorithm
199+
*out++ = ASN1_SEQUENCE;
200+
*out++ = 0x0a;
201+
*out++ = ASN1_OBJECT_IDENTIFIER;
202+
*out++ = 0x08;
203+
204+
// ECDSA with SHA256
205+
*out++ = 0x2a;
206+
*out++ = 0x86;
207+
*out++ = 0x48;
208+
*out++ = 0xce;
209+
*out++ = 0x3d;
210+
*out++ = 0x04;
211+
*out++ = 0x03;
212+
*out++ = 0x02;
213+
214+
const byte* r = &signature[0];
215+
const byte* s = &signature[32];
216+
217+
int rLength = 32;
218+
int sLength = 32;
219+
220+
while (*r == 0 && rLength) {
221+
r++;
222+
rLength--;
223+
}
224+
225+
while (*s == 0 && sLength) {
226+
s++;
227+
sLength--;
228+
}
229+
230+
if (*r & 0x80) {
231+
rLength++;
232+
}
233+
234+
if (*s & 0x80) {
235+
sLength++;
236+
}
237+
238+
*out++ = ASN1_BIT_STRING;
239+
*out++ = (rLength + sLength + 7);
240+
*out++ = 0;
241+
242+
*out++ = ASN1_SEQUENCE;
243+
*out++ = (rLength + sLength + 4);
244+
245+
*out++ = ASN1_INTEGER;
246+
*out++ = rLength;
247+
if ((*r & 0x80) && rLength) {
248+
*out++ = 0;
249+
rLength--;
250+
}
251+
memcpy(out, r, rLength);
252+
out += rLength;
253+
254+
*out++ = ASN1_INTEGER;
255+
*out++ = sLength;
256+
if ((*s & 0x80) && sLength) {
257+
*out++ = 0;
258+
sLength--;
259+
}
260+
memcpy(out, s, sLength);
261+
out += rLength;
262+
}
263+
264+
int ASN1UtilsClass::appendName(const String& name, int type, byte out[])
265+
{
266+
int nameLength = name.length();
267+
268+
*out++ = ASN1_SET;
269+
*out++ = nameLength + 9;
270+
271+
*out++ = ASN1_SEQUENCE;
272+
*out++ = nameLength + 7;
273+
274+
*out++ = ASN1_OBJECT_IDENTIFIER;
275+
*out++ = 0x03;
276+
*out++ = 0x55;
277+
*out++ = 0x04;
278+
*out++ = type;
279+
280+
*out++ = ASN1_PRINTABLE_STRING;
281+
*out++ = nameLength;
282+
memcpy(out, name.c_str(), nameLength);
283+
284+
return (nameLength + 11);
285+
}
286+
287+
void ASN1UtilsClass::appendSequenceHeader(int length, byte out[])
288+
{
289+
*out++ = ASN1_SEQUENCE;
290+
if (length > 255) {
291+
*out++ = 0x82;
292+
*out++ = (length >> 8) & 0xff;
293+
} else if (length > 127) {
294+
*out++ = 0x81;
295+
}
296+
*out++ = (length) & 0xff;
297+
}
298+
299+
300+
String ASN1UtilsClass::base64Encode(const byte in[], unsigned int length, const char* prefix, const char* suffix)
301+
{
302+
static const char* CODES = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
303+
304+
int b;
305+
String out;
306+
307+
int reserveLength = 4 * ((length + 2) / 3) + ((length / 3 * 4) / 76) + strlen(prefix) + strlen(suffix);
308+
out.reserve(reserveLength);
309+
310+
if (prefix) {
311+
out += prefix;
312+
}
313+
314+
for (unsigned int i = 0; i < length; i += 3) {
315+
if (i > 0 && (i / 3 * 4) % 76 == 0) {
316+
out += '\n';
317+
}
318+
319+
b = (in[i] & 0xFC) >> 2;
320+
out += CODES[b];
321+
322+
b = (in[i] & 0x03) << 4;
323+
if (i + 1 < length) {
324+
b |= (in[i + 1] & 0xF0) >> 4;
325+
out += CODES[b];
326+
b = (in[i + 1] & 0x0F) << 2;
327+
if (i + 2 < length) {
328+
b |= (in[i + 2] & 0xC0) >> 6;
329+
out += CODES[b];
330+
b = in[i + 2] & 0x3F;
331+
out += CODES[b];
332+
} else {
333+
out += CODES[b];
334+
out += '=';
335+
}
336+
} else {
337+
out += CODES[b];
338+
out += "==";
339+
}
340+
}
341+
342+
if (suffix) {
343+
out += suffix;
344+
}
345+
346+
return out;
347+
}
348+
349+
ASN1UtilsClass ASN1Utils;

0 commit comments

Comments
 (0)