Skip to content
This repository has been archived by the owner on Oct 12, 2023. It is now read-only.

Add due ethernet support #26

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
92 changes: 92 additions & 0 deletions build_all/base-libraries/AzureIoTUtility/src/sam/NTPClientAz.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
// Copyright (c) Arduino. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

#if defined(ARDUINO_ARCH_SAM)
#include "NTPClientAz.h"

#define LOCAL_UDP_PORT 2390

NTPClientAz::NTPClientAz() :
_udp()
{
}

int NTPClientAz::begin()
{
return _udp.begin(LOCAL_UDP_PORT);
}

uint32_t NTPClientAz::getEpochTime(const char* host, int port, unsigned long timeout)
{
if (host == NULL || port < 1) {
return (uint32_t)-1;
}

prepareRequest();
sendRequest(host, port);

if (!receiveResponse(timeout)) {
return (uint32_t)-1;
}

return parseResponse();
}

void NTPClientAz::end()
{
_udp.stop();
}

void NTPClientAz::prepareRequest()
{
memset(_buffer, 0, NTP_PACKET_SIZE);

// Initialize values needed to form NTP request
_buffer[0] = 0b11100011; // LI, Version, Mode
_buffer[1] = 0; // Stratum, or type of clock
_buffer[2] = 6; // Polling Interval
_buffer[3] = 0xEC; // Peer Clock Precision

// 8 bytes of zero for Root Delay & Root Dispersion

_buffer[12] = 49;
_buffer[13] = 0x4E;
_buffer[14] = 49;
_buffer[15] = 52;
}

void NTPClientAz::sendRequest(const char* host, int port)
{
_udp.beginPacket(host, port);
_udp.write(_buffer, NTP_PACKET_SIZE);
_udp.endPacket();
}

int NTPClientAz::receiveResponse(unsigned long timeout)
{
long start = millis();
int size = 0;

while(size == 0 && (millis() - start) < timeout) {
size = _udp.parsePacket();
}

if (size != NTP_PACKET_SIZE) {
return 0;
}

_udp.read(_buffer, NTP_PACKET_SIZE);

return 1;
}

uint32_t NTPClientAz::parseResponse()
{
uint16_t high = word(_buffer[40], _buffer[41]);
uint16_t low = word(_buffer[42], _buffer[43]);
uint32_t ntpTime = high << 16 | low; // since 1900
uint32_t epoch = ntpTime - 2208988800UL; // since 1970

return epoch;
}
#endif
38 changes: 38 additions & 0 deletions build_all/base-libraries/AzureIoTUtility/src/sam/NTPClientAz.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// Copyright (c) Arduino. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

#if defined(ARDUINO_ARCH_SAM)

#ifndef NTPCLIENT_AZ_H
#define NTPCLIENT_AZ_H

#include <SPI.h>
#include <EthernetLarge.h>
#include <EthernetUdp.h>

#define NTP_PACKET_SIZE 48
#define NTP_PORT 123

#define DEFAULT_NTP_TIMEOUT 10000

class NTPClientAz
{
public:
NTPClientAz();
int begin();
uint32_t getEpochTime(const char* host, int port = NTP_PORT, unsigned long timeout = DEFAULT_NTP_TIMEOUT);
void end();

private:
void prepareRequest();
void sendRequest(const char* host, int port);
int receiveResponse(unsigned long timeout);
uint32_t parseResponse();

char _buffer[NTP_PACKET_SIZE];
EthernetUDP _udp;
};

#endif // NTPCLIENT_AZ_H

#endif // ARDUINO_ARCH_SAM
214 changes: 214 additions & 0 deletions build_all/base-libraries/AzureIoTUtility/src/sam/pem_to_ta.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,214 @@

// Code here is pulled from curl sources, with the copyright and license
// shown below. I've extracted just one function (load_cafile) and converted
// it to read the certificate from a char array instead of a file.


/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 2019 - 2020, Michael Forney, <[email protected]>
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
***************************************************************************/

#include <memory>
#include <vector>
#include "bearssl.h"
#include <stdlib.h>
#include <string.h>
#include <Arduino.h>

#include "pem_to_ta.h"

struct cafile_parser
{
int err;
bool in_cert;
br_x509_decoder_context xc;
/* array of trust anchors loaded from CAfile */
br_x509_trust_anchor *anchors;
size_t anchors_len;
/* buffer for DN data */
unsigned char dn[1024];
size_t dn_len;
};

static void append_dn(void *ctx, const void *buf, size_t len)
{
struct cafile_parser *ca = (struct cafile_parser *)ctx;

if (ca->err != 0 || !ca->in_cert)
return;
if (sizeof(ca->dn) - ca->dn_len < len)
{
ca->err = CONV_FAILED_INIT;
return;
}
memcpy(ca->dn + ca->dn_len, buf, len);
ca->dn_len += len;
}

static void x509_push(void *ctx, const void *buf, size_t len)
{
struct cafile_parser *ca = (struct cafile_parser *)ctx;

if (ca->in_cert)
br_x509_decoder_push(&ca->xc, buf, len);
}

int pem_to_ta(const char *cer,
size_t cer_len,
br_x509_trust_anchor **anchors,
size_t *anchors_len)
{
struct cafile_parser ca;
br_pem_decoder_context pc;
br_x509_trust_anchor *ta;
size_t ta_size;
br_x509_trust_anchor *new_anchors;
size_t new_anchors_len;
br_x509_pkey *pkey;
const char *p;
const char *name;
size_t n, i, pushed;

ca.err = CONV_OK;
ca.in_cert = 0;
ca.anchors = NULL;
ca.anchors_len = 0;
br_pem_decoder_init(&pc);
br_pem_decoder_setdest(&pc, x509_push, &ca);
n = cer_len;
p = cer;

while (n)
{
pushed = br_pem_decoder_push(&pc, p, n);
if (ca.err)
goto fail;
p += pushed;
n -= pushed;
switch (br_pem_decoder_event(&pc))
{
case 0:
break;
case BR_PEM_BEGIN_OBJ:
name = br_pem_decoder_name(&pc);
//if(strcmp(name, "CERTIFICATE") && strcmp(name, "X509 CERTIFICATE"))
// break;
br_x509_decoder_init(&ca.xc, append_dn, &ca);
if (ca.anchors_len == SIZE_MAX / sizeof(ca.anchors[0]))
{
ca.err = CONV_OUT_OF_MEMORY;
goto fail;
}
new_anchors_len = ca.anchors_len + 1;
new_anchors = (br_x509_trust_anchor *)realloc(ca.anchors,
new_anchors_len * sizeof(ca.anchors[0]));
if (!new_anchors)
{
ca.err = CONV_OUT_OF_MEMORY;
goto fail;
}
ca.anchors = new_anchors;
ca.anchors_len = new_anchors_len;
ca.in_cert = 1;
ca.dn_len = 0;
ta = &ca.anchors[ca.anchors_len - 1];
ta->dn.data = NULL;
break;
case BR_PEM_END_OBJ:
if (!ca.in_cert)
break;
ca.in_cert = 0;
if (br_x509_decoder_last_error(&ca.xc))
{
ca.err = CONV_SSL_CACERT_BADFILE;
goto fail;
}
ta->flags = 0;
if (br_x509_decoder_isCA(&ca.xc))
ta->flags |= BR_X509_TA_CA;
pkey = br_x509_decoder_get_pkey(&ca.xc);
if (!pkey)
{
ca.err = CONV_SSL_CACERT_BADFILE;
goto fail;
}
ta->pkey = *pkey;

/* calculate space needed for trust anchor data */
ta_size = ca.dn_len;
switch (pkey->key_type)
{
case BR_KEYTYPE_RSA:
ta_size += pkey->key.rsa.nlen + pkey->key.rsa.elen;
break;
case BR_KEYTYPE_EC:
ta_size += pkey->key.ec.qlen;
break;
default:
ca.err = CONV_FAILED_INIT;
goto fail;
}

/* fill in trust anchor DN and public key data */
ta->dn.data = (unsigned char *)malloc(ta_size);
if (!ta->dn.data)
{
ca.err = CONV_OUT_OF_MEMORY;
goto fail;
}
memcpy(ta->dn.data, ca.dn, ca.dn_len);
ta->dn.len = ca.dn_len;
switch (pkey->key_type)
{
case BR_KEYTYPE_RSA:
ta->pkey.key.rsa.n = ta->dn.data + ta->dn.len;
memcpy(ta->pkey.key.rsa.n, pkey->key.rsa.n, pkey->key.rsa.nlen);
ta->pkey.key.rsa.e = ta->pkey.key.rsa.n + ta->pkey.key.rsa.nlen;
memcpy(ta->pkey.key.rsa.e, pkey->key.rsa.e, pkey->key.rsa.elen);
break;
case BR_KEYTYPE_EC:
ta->pkey.key.ec.q = ta->dn.data + ta->dn.len;
memcpy(ta->pkey.key.ec.q, pkey->key.ec.q, pkey->key.ec.qlen);
break;
}
break;
default:
ca.err = CONV_SSL_CACERT_BADFILE;
goto fail;
}
}
//}

fail:
if (ca.err == CONV_OK)
{
*anchors = ca.anchors;
*anchors_len = ca.anchors_len;
}
else
{
for (i = 0; i < ca.anchors_len; ++i)
free(ca.anchors[i].dn.data);
free(ca.anchors);
}

return ca.err;
}
18 changes: 18 additions & 0 deletions build_all/base-libraries/AzureIoTUtility/src/sam/pem_to_ta.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@

#ifndef PEM_TO_TA_H
#define PEM_TO_TA_H

#include "bearssl.h"

#define CONV_OK (0)
#define CONV_FAILED_INIT (2)
#define CONV_OUT_OF_MEMORY (27)
#define CONV_SSL_CACERT_BADFILE (77)

int pem_to_ta(const char *cer,
size_t cer_len,
br_x509_trust_anchor **anchors,
size_t *anchors_len);


#endif
Loading