Loading...
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 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 | /*
* Copyright (c) 2018 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <string.h>
#include <init.h>
#include <kernel.h>
#include "tls_internal.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(const struct device *unused)
{
(void)memset(credentials, 0, sizeof(credentials));
k_mutex_init(&credential_lock);
return 0;
}
SYS_INIT(credentials_init, APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT);
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;
}
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;
}
|