200 lines
3.7 KiB
C
200 lines
3.7 KiB
C
/*
|
|
* Copyright (c) 2018 Nordic Semiconductor ASA
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
#include <string.h>
|
|
|
|
#include <zephyr/init.h>
|
|
#include <zephyr/kernel.h>
|
|
|
|
#include "tls_internal.h"
|
|
#include "tls_credentials_digest_raw.h"
|
|
|
|
/* Global pool of credentials shared among TLS contexts. */
|
|
static struct tls_credential credentials[CONFIG_TLS_MAX_CREDENTIALS_NUMBER];
|
|
|
|
/* A mutex for protecting access to the credentials array. */
|
|
static struct k_mutex credential_lock;
|
|
|
|
static int credentials_init(void)
|
|
{
|
|
(void)memset(credentials, 0, sizeof(credentials));
|
|
|
|
k_mutex_init(&credential_lock);
|
|
|
|
return 0;
|
|
}
|
|
SYS_INIT(credentials_init, POST_KERNEL, 0);
|
|
|
|
static struct tls_credential *unused_credential_get(void)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < ARRAY_SIZE(credentials); i++) {
|
|
if (credentials[i].type == TLS_CREDENTIAL_NONE) {
|
|
return &credentials[i];
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
struct tls_credential *credential_get(sec_tag_t tag,
|
|
enum tls_credential_type type)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < ARRAY_SIZE(credentials); i++) {
|
|
if (credentials[i].type == type && credentials[i].tag == tag) {
|
|
return &credentials[i];
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
struct tls_credential *credential_next_get(sec_tag_t tag,
|
|
struct tls_credential *iter)
|
|
{
|
|
int i;
|
|
|
|
if (!iter) {
|
|
iter = credentials;
|
|
} else {
|
|
iter++;
|
|
}
|
|
|
|
for (i = iter - credentials; i < ARRAY_SIZE(credentials); i++) {
|
|
if (credentials[i].type != TLS_CREDENTIAL_NONE &&
|
|
credentials[i].tag == tag) {
|
|
return &credentials[i];
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
sec_tag_t credential_next_tag_get(sec_tag_t iter)
|
|
{
|
|
int i;
|
|
sec_tag_t lowest = TLS_SEC_TAG_NONE;
|
|
|
|
/* Scan all slots and find lowest sectag greater than iter */
|
|
for (i = 0; i < ARRAY_SIZE(credentials); i++) {
|
|
/* Skip empty slots. */
|
|
if (credentials[i].type == TLS_CREDENTIAL_NONE) {
|
|
continue;
|
|
}
|
|
|
|
/* Skip any slots containing sectags not greater than iter */
|
|
if (credentials[i].tag <= iter && iter != TLS_SEC_TAG_NONE) {
|
|
continue;
|
|
}
|
|
|
|
/* Find the lowest of such slots */
|
|
if (lowest == TLS_SEC_TAG_NONE || credentials[i].tag < lowest) {
|
|
lowest = credentials[i].tag;
|
|
}
|
|
}
|
|
|
|
return lowest;
|
|
}
|
|
|
|
int credential_digest(struct tls_credential *credential, void *dest, size_t *len)
|
|
{
|
|
return credential_digest_raw(credential, dest, len);
|
|
}
|
|
|
|
void credentials_lock(void)
|
|
{
|
|
k_mutex_lock(&credential_lock, K_FOREVER);
|
|
}
|
|
|
|
void credentials_unlock(void)
|
|
{
|
|
k_mutex_unlock(&credential_lock);
|
|
}
|
|
|
|
int tls_credential_add(sec_tag_t tag, enum tls_credential_type type,
|
|
const void *cred, size_t credlen)
|
|
{
|
|
struct tls_credential *credential;
|
|
int ret = 0;
|
|
|
|
credentials_lock();
|
|
|
|
credential = credential_get(tag, type);
|
|
if (credential != NULL) {
|
|
ret = -EEXIST;
|
|
goto exit;
|
|
}
|
|
|
|
credential = unused_credential_get();
|
|
if (credential == NULL) {
|
|
ret = -ENOMEM;
|
|
goto exit;
|
|
}
|
|
|
|
credential->tag = tag;
|
|
credential->type = type;
|
|
credential->buf = cred;
|
|
credential->len = credlen;
|
|
|
|
exit:
|
|
credentials_unlock();
|
|
|
|
return ret;
|
|
}
|
|
|
|
int tls_credential_get(sec_tag_t tag, enum tls_credential_type type,
|
|
void *cred, size_t *credlen)
|
|
{
|
|
struct tls_credential *credential;
|
|
int ret = 0;
|
|
|
|
credentials_lock();
|
|
|
|
credential = credential_get(tag, type);
|
|
if (credential == NULL) {
|
|
ret = -ENOENT;
|
|
goto exit;
|
|
}
|
|
|
|
if (credential->len > *credlen) {
|
|
ret = -EFBIG;
|
|
goto exit;
|
|
}
|
|
|
|
*credlen = credential->len;
|
|
memcpy(cred, credential->buf, credential->len);
|
|
|
|
exit:
|
|
credentials_unlock();
|
|
|
|
return ret;
|
|
}
|
|
|
|
int tls_credential_delete(sec_tag_t tag, enum tls_credential_type type)
|
|
{
|
|
struct tls_credential *credential;
|
|
int ret = 0;
|
|
|
|
credentials_lock();
|
|
|
|
credential = credential_get(tag, type);
|
|
|
|
if (!credential) {
|
|
ret = -ENOENT;
|
|
goto exit;
|
|
}
|
|
|
|
(void)memset(credential, 0, sizeof(struct tls_credential));
|
|
credential->type = TLS_CREDENTIAL_NONE;
|
|
|
|
exit:
|
|
credentials_unlock();
|
|
|
|
return ret;
|
|
}
|