-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathSElementJWS.cpp
126 lines (96 loc) · 3.02 KB
/
SElementJWS.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
/*
This file is part of the Arduino_SecureElement library.
Copyright (c) 2024 Arduino SA
This Source Code Form is subject to the terms of the Mozilla Public
License, v. 2.0. If a copy of the MPL was not distributed with this
file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
/******************************************************************************
* INCLUDE
******************************************************************************/
#include <utility/SElementJWS.h>
#include <ArduinoECCX08.h>
#include <utility/ASN1Utils.h>
#include <utility/PEMUtils.h>
static String base64urlEncode(const byte in[], unsigned int length)
{
static const char* CODES = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_=";
int b;
String out;
int reserveLength = 4 * ((length + 2) / 3);
out.reserve(reserveLength);
for (unsigned int i = 0; i < length; i += 3) {
b = (in[i] & 0xFC) >> 2;
out += CODES[b];
b = (in[i] & 0x03) << 4;
if (i + 1 < length) {
b |= (in[i + 1] & 0xF0) >> 4;
out += CODES[b];
b = (in[i + 1] & 0x0F) << 2;
if (i + 2 < length) {
b |= (in[i + 2] & 0xC0) >> 6;
out += CODES[b];
b = in[i + 2] & 0x3F;
out += CODES[b];
} else {
out += CODES[b];
}
} else {
out += CODES[b];
}
}
while (out.lastIndexOf('=') != -1) {
out.remove(out.length() - 1);
}
return out;
}
String SElementJWS::publicKey(SecureElement & se, int slot, bool newPrivateKey)
{
if (slot < 0 || slot > 8) {
return "";
}
byte publicKey[64];
if (newPrivateKey) {
if (!se.generatePrivateKey(slot, publicKey)) {
return "";
}
} else {
if (!se.generatePublicKey(slot, publicKey)) {
return "";
}
}
int length = ASN1Utils.publicKeyLength();
byte out[length];
ASN1Utils.appendPublicKey(publicKey, out);
return PEMUtils.base64Encode(out, length, "-----BEGIN PUBLIC KEY-----\n", "\n-----END PUBLIC KEY-----\n");
}
String SElementJWS::sign(SecureElement & se, int slot, const char* header, const char* payload)
{
if (slot < 0 || slot > 8) {
return "";
}
String encodedHeader = base64urlEncode((const byte*)header, strlen(header));
String encodedPayload = base64urlEncode((const byte*)payload, strlen(payload));
String toSign;
toSign.reserve(encodedHeader.length() + 1 + encodedPayload.length());
toSign += encodedHeader;
toSign += '.';
toSign += encodedPayload;
byte toSignSha256[32];
byte signature[64];
se.SHA256((const uint8_t*)toSign.c_str(), toSign.length(), toSignSha256);
if (!se.ecSign(slot, toSignSha256, signature)) {
return "";
}
String encodedSignature = base64urlEncode(signature, sizeof(signature));
String result;
result.reserve(toSign.length() + 1 + encodedSignature.length());
result += toSign;
result += '.';
result += encodedSignature;
return result;
}
String SElementJWS::sign(SecureElement & se, int slot, const String& header, const String& payload)
{
return sign(se, slot, header.c_str(), payload.c_str());
}