5 #include <esp32-hal-log.h>
6 #include <HTTPClient.h>
7 #include "WiFiClientSecure.h"
9 #include "mbedtls/timing.h"
10 #include "mbedtls/sha256.h"
11 #include "mbedtls/bignum.h"
12 #include "mbedtls/ctr_drbg.h"
13 #include "mbedtls/rsa.h"
14 #include "mbedtls/pk.h"
15 #include "mbedtls/base64.h"
29 this->headerName = hN;
37 this->headerName = hN;
38 this->headerValue = hV;
168 WiFiClientSecure client;
189 char* timeServer=
"pool.ntp.org",
190 long gmtOffsetSeconds=0,
191 int daylightOffsetSeconds=0
204 const unsigned char* toEncrypt,
205 unsigned char (&encoded)[500]
207 mbedtls_pk_context pk;
208 mbedtls_pk_init(&pk);
213 pwdLen = strlen(pwd);
216 mbedtls_rsa_context *rsa = mbedtls_pk_rsa(pk);
218 int keyValid = mbedtls_rsa_check_privkey(rsa);
219 unsigned char encryptBuffer[512];
220 if( keyValid == 0 ) {
222 mbedtls_sha256(toEncrypt, strlen((
char*) toEncrypt), hashResult, 0);
223 int success = mbedtls_rsa_rsassa_pkcs1_v15_sign( rsa, NULL, NULL, MBEDTLS_RSA_PRIVATE, MBEDTLS_MD_SHA256, strlen((
char*) hashResult), hashResult, encryptBuffer );
224 size_t encodedOutLen;
225 mbedtls_base64_encode( encoded,
sizeof(encoded), &encodedOutLen, (
const unsigned char*) encryptBuffer,
sizeof(encryptBuffer) / 2 );
236 unsigned char encoded[500];
239 size_t contentLen = 0;
240 if( request.
content != NULL ) contentLen = strlen(request.
content);
241 unsigned char contentEncoded[64] =
"";
242 char contentLenStr[10] =
"0";
243 sprintf(contentLenStr,
"%d", contentLen);
246 char signingString[400] =
"";
247 strcat(signingString,
"(request-target): ");
251 strcat(signingString, meth);
252 strcat(signingString,
" ");
253 strcat(signingString, request.
path);
254 strcat(signingString,
"\n");
256 while(!getLocalTime(&timeinfo)){
257 Serial.println(
"Failed to obtain time");
260 strftime(timestamp, 35,
"%a, %d %b %Y %H:%M:%S GMT" , &timeinfo);
261 strcat(signingString,
"date: ");
262 strcat(signingString, timestamp);
263 strcat(signingString,
"\n");
265 strcat(signingString,
"host: ");
266 strcat(signingString, request.
host);
268 strcat(signingString,
"\n");
270 byte contentHash[32];
271 mbedtls_sha256((
const unsigned char*) request.
content, strlen((
char*) request.
content), contentHash, 0);
272 size_t contentEncodedOutLen;
273 mbedtls_base64_encode(contentEncoded, 64, &contentEncodedOutLen, (
const unsigned char*) contentHash,
sizeof(contentHash));
274 strcat(signingString,
"x-content-sha256: ");
275 strcat(signingString, (
char*) contentEncoded);
276 strcat(signingString,
"\n");
279 strcat(signingString,
"content-length: ");
280 strcat(signingString, contentLenStr);
281 strcat(signingString,
"\n");
284 strcat(signingString,
"content-type: ");
290 char authHeader[800] =
"Signature version=\"1\",headers=\"(request-target) date host";
291 if(putPost) strcat(authHeader,
" x-content-sha256 content-length content-type");
292 strcat(authHeader,
"\",keyId=\"");
294 strcat(authHeader,
"/");
296 strcat(authHeader,
"/");
298 strcat(authHeader,
"\",algorithm=\"rsa-sha256\",signature=\"");
299 strcat(authHeader, ((
char*) encoded));
300 strcat(authHeader,
"\"");
302 String url =
"https://" + String(request.
host) + String(request.
path);
324 client.setInsecure();
327 log_v(
"Connecting to %s on 443", request.
host);
328 if( !client.connect(request.
host, 443) ) {
329 Serial.println(
"Connection failed!");
332 client.println(String(request.
requestMethod) +
" " + url +
" HTTP/1.1");
335 client.println(
"date: " + String(timestamp));
336 log_v(
"date: %s", (
char*) timestamp);
337 client.println(
"Authorization: " + String( (
char*) authHeader));
338 log_v(
"Authorization: %s", (
char*) authHeader);
339 client.println(
"host: " + String(request.
host));
340 log_v(
"Host: %s", (
char*) request.
host);
342 client.println(
"x-content-sha256: " + String((
char*) contentEncoded));
343 log_v(
"x-content-sha256: %s", (
char*) contentEncoded);
349 client.println(String(hN) +
": " + String(hV));
350 log_v(
"%s : %s", hN, hV);
352 client.println(
"content-type: " + String(request.
contentType));
354 client.print(
"content-length: ");
355 client.println(contentLenStr);
356 log_v(
"content-length: %s", contentLenStr);
357 client.println(
"Connection: close");
358 log_v(
"Connection: close");
361 client.println(request.
content);
363 bool firstLine =
true;
364 while (client.connected()) {
365 size_t len = client.available();
367 String line = client.readStringUntil(
'\n');
371 int codePos = line.indexOf(
' ') + 1;
372 response.
statusCode = line.substring(codePos, line.indexOf(
' ', codePos)).toInt();
373 log_v(
"Set status code to: %d", response.
statusCode);
377 line.toCharArray(headerStr,
sizeof(headerStr));
380 char* separator = strchr(headerStr,
':');
384 char* hN = headerStr;
386 char* hV = &separator[1];
390 log_v(
"Setting requested response header: %s to value %s", hN, hV);
396 log_v(
"Response Header: %s", line.c_str());
398 log_v(
"Headers Received");
406 String clientResponse =
"";
407 while (client.available()) {
408 clientResponse.concat(client.readString());
The OCI API.
Definition: oci.h:166
Oci(OciProfile profile, char *timeServer="pool.ntp.org", long gmtOffsetSeconds=0, int daylightOffsetSeconds=0)
Construct a new instance of the OCI API.
Definition: oci.h:187
const char * HTTP_METHOD_DELETE
HTTP DELETE.
Definition: oci.h:174
char * ntpServer
The ntpServer.
Definition: oci.h:177
const char * HTTP_METHOD_POST
HTTP POST.
Definition: oci.h:171
const char * HTTP_METHOD_PUT
HTTP PUT.
Definition: oci.h:172
void encryptAndEncode(const unsigned char *toEncrypt, unsigned char(&encoded)[500])
Used internally to hash, sign and base64 encode the auth header to sign the request.
Definition: oci.h:203
OciProfile ociProfile
The OciProfile to use.
Definition: oci.h:176
void apiCall(OciApiRequest request, OciApiResponse &response)
Make a call to the OCI REST API.
Definition: oci.h:232
long gmtOffset
The offset from GMT to use for retrieving time. You shouldn't change this - requests should be signed...
Definition: oci.h:178
const char * HTTP_METHOD_GET
HTTP GET.
Definition: oci.h:170
const char * HTTP_METHOD_PATCH
HTTP PATCH.
Definition: oci.h:173
int daylightOffset
The daylight savings offset. Should not change this either.
Definition: oci.h:179
A request contains all of the information required to make a call to the OCI API.
Definition: oci.h:49
ociApiRequest(char *host, char *path, const char *requestMethod, Header *requestHeaders={}, int requestHeaderCount=0, char *endpointCert=NULL, char *content="", char *contentType="application/json")
An OCI API request.
Definition: oci.h:69
const char * requestMethod
The HTTP method. See Oci for const values.
Definition: oci.h:52
Header * requestHeaders
An array of Header objects (set both key and value)
Definition: oci.h:56
char * contentType
The content type.
Definition: oci.h:55
char * host
The REST API endpoint host. Ex: objectstorage.us-phoenix-1.oraclecloud.com.
Definition: oci.h:50
char * content
The body to be passed to the API call.
Definition: oci.h:54
int requestHeaderCount
The count of headers in the requestHeaders array.
Definition: oci.h:57
char * endpointCert
The text value of the Root CA cert for the API endpoint. Used to make secure connections....
Definition: oci.h:53
char * path
The path. Ex: "/n/".
Definition: oci.h:51
Contains the response from an API call.
Definition: oci.h:95
ociApiResponse(String response, int statusCode, String opcRequestId, String errorMsg, Header *responseHeaders={}, int responseHeaderCount=0)
Construct a full response object.
Definition: oci.h:120
ociApiResponse(Header *responseHeaders={}, int responseHeaderCount=0)
Construct a response with an array of headers and the count.
Definition: oci.h:107
int responseHeaderCount
The count of headers to collect.
Definition: oci.h:101
String response
The string returned from the API call. Usually JSON.
Definition: oci.h:96
String opcRequestId
The opc-request-id
Definition: oci.h:98
int statusCode
The HTTP status code returned.
Definition: oci.h:97
String errorMsg
Any error message returned from the API call.
Definition: oci.h:99
Header * responseHeaders
An array of headers to collect from the API call.
Definition: oci.h:100
Contains the OCIDs and key & key related data necessary to sign the request.
Definition: oci.h:135
char * privateKeyPassphrase
Optional - the private key password (for protected keys)
Definition: oci.h:140
ociProfile()
Construct an instance of OciProfile.
Definition: oci.h:144
char * privateKey
The private key text. must be null terminated! (have a newline at the end of the text)
Definition: oci.h:139
char * tenancyOcid
The tenancy OCID.
Definition: oci.h:136
char * keyFingerprint
The key fingerprint.
Definition: oci.h:138
ociProfile(char *tenancyOcid, char *userOcid, char *keyFingerprint, char *privateKey, char *privateKeyPassphrase=NULL)
Construct an instance of OciProfile.
Definition: oci.h:153
char * userOcid
The user OCID.
Definition: oci.h:137