1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00
RIOT/sys/uuid/uuid.c
2018-10-03 10:44:14 +02:00

170 lines
4.4 KiB
C

/*
* Copyright (C) 2018 Freie Universität Berlin
* Copyright (C) 2018 Inria
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @ingroup sys_uuid
* @{
* @file
* @brief Function implementations to create RFC 4122 UUID objects
*
* @author Koen Zandberg <koen@bergzand.net>
* @}
*/
#include <string.h>
#include "byteorder.h"
#include "hashes/md5.h"
#include "hashes/sha1.h"
#include "random.h"
#include "uuid.h"
#include "fmt.h"
const uuid_t uuid_namespace_dns = { /* 6ba7b810-9dad-11d1-80b4-00c04fd430c8 */
.time_low.u8 = { 0x6b, 0xa7, 0xb8, 0x10 },
.time_mid.u8 = { 0x9d, 0xad },
.time_hi.u8 = { 0x11, 0xd1 },
.clk_seq_hi_res = 0x80,
.clk_seq_low = 0xb4,
.node = { 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8 }
};
const uuid_t uuid_namespace_url = { /* 6ba7b811-9dad-11d1-80b4-00c04fd430c8 */
.time_low.u8 = { 0x6b, 0xa7, 0xb8, 0x11 },
.time_mid.u8 = { 0x9d, 0xad },
.time_hi.u8 = { 0x11, 0xd1 },
.clk_seq_hi_res = 0x80,
.clk_seq_low = 0xb4,
.node = { 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8 }
};
/* Name string is an ISO OID */
const uuid_t uuid_namespace_iso = { /* 6ba7b812-9dad-11d1-80b4-00c04fd430c8 */
.time_low.u8 = { 0x6b, 0xa7, 0xb8, 0x12 },
.time_mid.u8 = { 0x9d, 0xad },
.time_hi.u8 = { 0x11, 0xd1 },
.clk_seq_hi_res = 0x80,
.clk_seq_low = 0xb4,
.node = { 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8 }
};
const uuid_t uuid_namespace_x500 = { /* 6ba7b814-9dad-11d1-80b4-00c04fd430c8 */
.time_low.u8 = { 0x6b, 0xa7, 0xb8, 0x14 },
.time_mid.u8 = { 0x9d, 0xad },
.time_hi.u8 = { 0x11, 0xd1 },
.clk_seq_hi_res = 0x80,
.clk_seq_low = 0xb4,
.node = { 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8 }
};
static inline void _set_version(uuid_t *uuid, unsigned version)
{
uint16_t time_hi = byteorder_ntohs(uuid->time_hi) & 0x0fff;
time_hi |= (version << 12);
uuid->time_hi = byteorder_htons(time_hi);
}
static inline void _set_reserved(uuid_t *uuid)
{
uuid->clk_seq_hi_res = (uuid->clk_seq_hi_res & 0x3f) | 0x80;
}
void uuid_v3(uuid_t *uuid, const uuid_t *ns, const uint8_t *name, size_t len)
{
/* Digest calculation */
md5_ctx_t ctx;
md5_init(&ctx);
md5_update(&ctx, ns, sizeof(uuid_t));
md5_update(&ctx, name, len);
md5_final(&ctx, uuid);
_set_version(uuid, UUID_V3);
_set_reserved(uuid);
}
void uuid_v4(uuid_t *uuid)
{
random_bytes((uint8_t *)uuid, sizeof(uuid_t));
_set_version(uuid, UUID_V4);
_set_reserved(uuid);
}
void uuid_v5(uuid_t *uuid, const uuid_t *ns, const uint8_t *name, size_t len)
{
uint8_t digest[20];
sha1_context ctx;
sha1_init(&ctx);
sha1_update(&ctx, ns, sizeof(uuid_t));
sha1_update(&ctx, name, len);
sha1_final(&ctx, digest);
memcpy(uuid, digest, sizeof(uuid_t));
_set_version(uuid, UUID_V5);
_set_reserved(uuid);
}
void uuid_to_string(const uuid_t *uuid, char *str)
{
char *p = str;
p += fmt_u32_hex(p, byteorder_ntohl(uuid->time_low));
p += fmt_char(p, '-');
p += fmt_u16_hex(p, byteorder_ntohs(uuid->time_mid));
p += fmt_char(p, '-');
p += fmt_u16_hex(p, byteorder_ntohs(uuid->time_hi));
p += fmt_char(p, '-');
p += fmt_byte_hex(p, uuid->clk_seq_hi_res);
p += fmt_byte_hex(p, uuid->clk_seq_low);
p += fmt_char(p, '-');
p += fmt_bytes_hex(p, uuid->node, UUID_NODE_LEN);
*p = '\0';
fmt_to_lower(str, str);
}
int uuid_from_string(uuid_t *uuid, const char *str)
{
uint32_t tmp;
if (fmt_strlen(str) < UUID_STR_LEN) {
return -1;
}
tmp = scn_u32_hex(str, 8);
uuid->time_low = byteorder_htonl(tmp);
str += 8;
if (*str++ != '-') {
return -2;
}
tmp = scn_u32_hex(str, 4);
uuid->time_mid = byteorder_htons(tmp);
str += 4;
if (*str++ != '-') {
return -2;
}
tmp = scn_u32_hex(str, 4);
uuid->time_hi = byteorder_htons(tmp);
str += 4;
if (*str++ != '-') {
return -2;
}
uuid->clk_seq_hi_res = scn_u32_hex(str, 2);
str += 2;
uuid->clk_seq_low = scn_u32_hex(str, 2);
str += 2;
if (*str++ != '-') {
return -2;
}
for (unsigned i = 0; i < UUID_NODE_LEN; i++) {
uuid->node[i] = scn_u32_hex(str, 2);
str += 2;
}
return 0;
}