/*
Unix SMB/CIFS implementation.
Group Key Distribution Protocol functions
Copyright (C) Catalyst.Net Ltd 2023
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see .
*/
#ifndef LIB_CRYPTO_GKDI_H
#define LIB_CRYPTO_GKDI_H
#include
#include
#include "lib/util/data_blob.h"
#include "libcli/util/ntstatus.h"
#include "librpc/gen_ndr/misc.h"
#include "lib/util/time.h"
#include "talloc.h"
enum KdfAlgorithmId {
KDF_ALGORITHM_SP800_108_CTR_HMAC,
};
enum KdfSp800_108Param {
KDF_PARAM_SHA1,
KDF_PARAM_SHA256,
KDF_PARAM_SHA384,
KDF_PARAM_SHA512,
};
struct KdfAlgorithm {
union {
enum KdfSp800_108Param sp800_108;
} param;
enum KdfAlgorithmId id;
};
enum {
root_key_version_1 = 1,
};
struct ProvRootKey {
struct GUID id;
DATA_BLOB data;
NTTIME create_time;
NTTIME use_start_time;
const char *domain_id;
struct KdfAlgorithm kdf_algorithm;
int32_t version;
};
NTSTATUS ProvRootKey(TALLOC_CTX *mem_ctx,
const struct GUID root_key_id,
const int32_t version,
const DATA_BLOB root_key_data,
const NTTIME create_time,
const NTTIME use_start_time,
const char *const domain_id,
const struct KdfAlgorithm kdf_algorithm,
const struct ProvRootKey **const root_key_out);
struct Gkid {
int32_t l0_idx;
int8_t l1_idx; /* [range(0, 31)] */
int8_t l2_idx; /* [range(0, 31)] */
};
enum GkidType {
GKID_DEFAULT = -1,
GKID_L0_SEED_KEY = 0,
GKID_L1_SEED_KEY = 1,
GKID_L2_SEED_KEY = 2,
};
/*
* Construct a GKID. The caller must check the returned GKID is valid before
* using it!
*/
static inline struct Gkid Gkid(int32_t l0_idx, int8_t l1_idx, int8_t l2_idx)
{
return (struct Gkid){l0_idx, l1_idx, l2_idx};
}
static const struct Gkid invalid_gkid = {
INT32_MIN,
INT8_MIN,
INT8_MIN,
};
static const uint32_t key_envelope_magic = 0x4b53444b; /* ‘KDSK’ */
struct KeyEnvelopeId {
struct GUID root_key_id;
struct Gkid gkid;
};
struct KeyEnvelope;
NTSTATUS gkdi_pull_KeyEnvelope(TALLOC_CTX *mem_ctx,
const DATA_BLOB *pwd_id_blob,
struct KeyEnvelope *pwd_id_out);
const struct KeyEnvelopeId *gkdi_pull_KeyEnvelopeId(
const DATA_BLOB key_env,
struct KeyEnvelopeId *key_env_out);
enum GkidType gkid_key_type(const struct Gkid gkid);
bool gkid_is_valid(const struct Gkid gkid);
static const int gkdi_l1_key_iteration = 32;
static const int gkdi_l2_key_iteration = 32;
static const int64_t gkdi_key_cycle_duration = 360000000000; /* ten hours */
static const int64_t gkdi_max_clock_skew = 3000000000; /* five minutes */
#define GKDI_KEY_LEN 64
struct Gkid gkdi_get_interval_id(const NTTIME time);
NTTIME gkdi_get_key_start_time(const struct Gkid gkid);
NTTIME gkdi_get_interval_start_time(const NTTIME time);
bool gkid_less_than_or_equal_to(const struct Gkid g1, const struct Gkid g2);
bool gkdi_rollover_interval(const int64_t managed_password_interval,
NTTIME *result);
gnutls_mac_algorithm_t get_sp800_108_mac_algorithm(
const struct KdfAlgorithm kdf_algorithm);
NTSTATUS compute_seed_key(TALLOC_CTX *mem_ctx,
const DATA_BLOB target_security_descriptor,
const struct ProvRootKey *const root_key,
const struct Gkid gkid,
uint8_t out[static const GKDI_KEY_LEN]);
NTSTATUS kdf_sp_800_108_from_params(
const DATA_BLOB *const kdf_param,
struct KdfAlgorithm *const kdf_algorithm_out);
NTSTATUS kdf_algorithm_from_params(
const char *const kdf_algorithm_id,
const DATA_BLOB *const kdf_param,
struct KdfAlgorithm *const kdf_algorithm_out);
#endif /* LIB_CRYPTO_GKDI_H */