1 /** \ingroup DailyTracingKey
3 * @author David Llewellyn-Jones <david@flypig.co.uk>
8 * Copyright David Llewellyn-Jones, 2020
9 * Released under the GPLv2.
11 * @brief Daily Tracing Key functionality
12 * @section DESCRIPTION
14 * This class is used to generate and manage the Daily Tracing Key. It's
15 * largely internal. The functionality from \ref Contrac should generally be
16 * used instead of these functions.
20 /** \addtogroup DailyTracingKey
31 #include <openssl/crypto.h>
32 #include <openssl/kdf.h>
33 #include <openssl/err.h>
34 #include <openssl/evp.h>
36 #include "contrac/contrac.h"
37 #include "contrac/utils.h"
38 #include "contrac/log.h"
40 #include "contrac/dtk.h"
47 * This is the prefix for the Info parameter provided to the HKDF and used to
50 #define DTK_INFO_PREFIX "CT-DTK"
55 * @brief The structure used to represent a Daily Tracing Key.
57 * This is an opaque structure that contains information about the DTK..
59 * This must be passed as the first parameter of every non-static function.
61 * The structure typedef is in dtk.h
65 unsigned char dtk
[DTK_SIZE
];
69 // Function prototypes
71 // Function definitions
74 * Create a new instance of the class.
76 * @return The newly created object.
81 data
= calloc(sizeof(Dtk
), 1);
87 * Delete an instance of the class, freeing up the memory allocated to it.
89 * @param data The instance to free.
91 void dtk_delete(Dtk
* data
) {
93 // Clear the data for security
94 memset(data
, 0, sizeof(Dtk
));
101 * Generate a random Daily Tracing Key.
103 * The operation may fail under certain circumstances, such as if the
104 * HKDF operation fails for some reason.
106 * For internal use. It generally makes more sense to use the
107 * contrac_set_day_number() function instead.
109 * @param data The context object to work with.
110 * @return true if the operation completed successfully, false otherwise.
112 bool dtk_generate_daily_key(Dtk
* data
, Contrac
const * contrac
, uint32_t day_number
) {
114 char encode
[sizeof(DTK_INFO_PREFIX
) + sizeof(day_number
)];
115 size_t out_length
= 0;
116 EVP_PKEY_CTX
*pctx
= NULL
;
117 const unsigned char * tk
;
119 // dtk_i <- HKDF(tk, NULL, (UTF8("CT-DTK") || D_i), 16)
122 // Produce Info sequence UTF8("CT-DTK") || D_i)
123 // From the spec it's not clear whether this is string or byte concatenation.
124 // Here we use byte, but it might have to be changed
125 memcpy(encode
, DTK_INFO_PREFIX
, sizeof(DTK_INFO_PREFIX
));
126 ((uint32_t *)(encode
+ sizeof(DTK_INFO_PREFIX
)))[0] = day_number
;
128 pctx
= EVP_PKEY_CTX_new_id(EVP_PKEY_HKDF
, NULL
);
130 result
= EVP_PKEY_derive_init(pctx
);
134 result
= EVP_PKEY_CTX_set_hkdf_md(pctx
, EVP_sha256());
138 result
= EVP_PKEY_CTX_set1_hkdf_salt(pctx
, NULL
, 4);
142 tk
= contrac_get_tracing_key(contrac
);
143 result
= EVP_PKEY_CTX_set1_hkdf_key(pctx
, tk
, TK_SIZE
);
147 result
= EVP_PKEY_CTX_add1_hkdf_info(pctx
, encode
, sizeof(encode
));
151 out_length
= DTK_SIZE
;
152 result
= EVP_PKEY_derive(pctx
, data
->dtk
, &out_length
);
155 if ((result
> 0) && (out_length
== DTK_SIZE
)) {
156 data
->day_number
= day_number
;
161 LOG(LOG_ERR
, "Error generating daily key: %lu\n", ERR_get_error());
164 // Freeing a NULL value is safe
165 EVP_PKEY_CTX_free(pctx
);
170 const unsigned char * dtk_get_daily_key(Dtk
const * data
) {
174 uint32_t dtk_get_day_number(Dtk
const * data
) {
175 return data
->day_number
;
178 void dtk_assign(Dtk
* data
, unsigned char const * dtk_bytes
, uint32_t day_number
) {
179 memcpy(data
->dtk
, dtk_bytes
, DTK_SIZE
);
180 data
->day_number
= day_number
;
183 /** @} addtogroup DailyTracingKey */