summaryrefslogtreecommitdiff
path: root/cesar/cp/secu/src/secu_lib.c
blob: 73e9ddd45bb6b84b08cb92090fa733ce25baf5b4 (plain)
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
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
/* Cesar project {{{
 *
 * Copyright (C) 2007 Spidcom
 *
 * <<<Licence>>>
 *
 * }}} */
/**
 * \file    cp/secu/secu_lib.c
 * \brief   all security related function
 * \ingroup cp_secu
 *
 */

#include "common/std.h"
#include "cp/secu/secu.h"

static peks_t m_peks;     // see p588
static u8 m_eks;          // see p122

static aes_key_t m_dak[THEORICAL_MAX_STA_NB];
static aes_key_t m_tek[PEKS_TEKD + 1];
static aes_key_t m_nmk;


void 
secu_init (cp_secu_t *p_sec)
{
    dbg_assert (p_sec);
    
    memset (p_sec, 0, sizeof(cp_secu_t));
    memset (m_dak, 0, sizeof(m_dak));
    memset (m_tek, 0, sizeof(m_tek));

    m_peks = PEKS_NOT_ENCRYPTED;
    m_eks = 0xF;    // 0xF : no encryption key
#ifndef DEBUG
    /* TODO
     * ici, lire DAK, NMK, Security Level
     */
#error "paramètres à charger à partir de la flash"
#else // utilisons des valeurs par défaut
    // choisissons un DAK...                       
    memcpy(p_sec->security_parameters.dak, "un DAK au pif...", AES_KEY_SIZE);
    // choisissons la première NMK
    memcpy(p_sec->security_parameters.nmk[0].nmk, "NMK au pif...   ", AES_KEY_SIZE);
    memcpy(p_sec->security_parameters.nmk[0].nid, "un NID ", NID_SIZE);
    p_sec->security_parameters.nmk[0].sl = SIMPLE_CONNECT;
    // choisissons la seconde NMK
    memcpy(p_sec->security_parameters.nmk[1].nmk, "seconde NMK au p", AES_KEY_SIZE);
    secu_hash(PWD_NMK, p_sec->security_parameters.nmk[1].nmk, AES_KEY_SIZE, p_sec->security_parameters.nmk[1].nid);
    p_sec->security_parameters.nmk[1].sl = SIMPLE_CONNECT;
#endif

    secu_p_run_init();
}

void
cp_secu_uninit (cp_secu_t *ctx)
{
    dbg_assert (ctx);
}

struct pbkdf1_params_t
{
    u8 salt[SALT_SIZE];
    int salt_len;
    int it_count;
    int out_key_size;
};

E_ErrCode 
secu_hash (pwd_type_t pwd_type, u8 in[], int in_len, u8 out[])
{
    E_ErrCode res;
    u8 str[OUTPUT_KEY_SIZE];
    struct pbkdf1_params_t pbkdf1params[] = 
    {
        { { 0x08, 0x85, 0x6D, 0xAF, 0x7C, 0xF5, 0x81, 0x85 }, 8, 1000, 16 }, // obtenir DAK depuis DPW (7.10.7.1)
        { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, 0, 5, NID_SIZE }, // obtenir "NID offset" depuis NMK (4.4.3.1)
        { { 0x08, 0x85, 0x6D, 0xAF, 0x7C, 0xF5, 0x81, 0x86 }, 8, 1000, 16 }, // obtenir NMK-HS (7.10.7.1)
        { { 0x58, 0x56, 0x52, 0xf6, 0x9c, 0x04, 0xb5, 0x72 }, 8, 1000, 16 }, // Test
        { { 0x08, 0x85, 0x6D, 0xAF, 0x7C, 0xF5, 0x81, 0x86 }, 8, 1000, 16 } // obtenir NMK depuis NPW
    };
#ifdef DEBUG
    uint i;
    for(i=0 ; i<COUNT(pbkdf1params) ; i++)
    {
        if(pbkdf1params[i].out_key_size > OUTPUT_KEY_SIZE) exit(EXIT_FAILURE);
    }
    if(pwd_type >= COUNT(pbkdf1params) ) exit(EXIT_FAILURE);
#endif

    dbg_assert (in);
    dbg_assert (out);

    if ( (pwd_type == PWD_DPW) || (pwd_type == PWD_NPW) )
    {
        if ( (res = secu_check_password_validity (pwd_type, in)) != Success)
            return res;
    }
    if ( (res = secu_pbkdf1(in, in_len, pbkdf1params[pwd_type].salt, pbkdf1params[pwd_type].salt_len, pbkdf1params[pwd_type].it_count, str) != Success))
        return res;
    memcpy(out, str, pbkdf1params[pwd_type].out_key_size);
    return Success;
}

E_ErrCode 
secu_gen_aes_key (u8 key[])
{
    u8 tmp_key[SHA256_OUTPUT_SIZE];
    aes_context ctx;
    gen_key_t sec;

    dbg_assert (key);

#ifndef DEBUG
    /*
     * TODO ici, lire les paramètres de génération de la clé aléatoire,
     * puis incrémenter le compteur et le réécrire dans la flash.
     */
#error "paramètres à charger à partir de la flash"
#else // utilisons des valeurs par défaut
    memcpy(sec.key, "une cle choisie ", AES_KEY_SIZE);
    sec.count = 456;
#endif
    /*
     * generate a pseudo-random number
     */
    sha2 ((u8*) &sec.count, sizeof(sec.count), tmp_key, 0);
    /*
     * generate an aes key from this number
     */
    aes_set_key( &ctx, sec.key, AES_KEY_SIZE * 8);
    aes_encrypt( &ctx, tmp_key, key);
    return Success;
}

aes_key_t *
secu_get_ek_from_peks(const peks_t peks, const tei_t tei)
{
    dbg_assert(peks < PEKS_NOT_ENCRYPTED);
    dbg_assert(tei != 0 && tei != 0xFF);
    
    if(peks == PEKS_DESTINATION_STA_DAK) return &m_dak[tei];
    if(peks == PEKS_NMK) return &m_nmk;
    if(peks == PEKS_NOT_ENCRYPTED) return NULL;
    return &m_tek[peks];
}

void
secu_set_sta_s_dak(const tei_t tei, const aes_key_t dak)
{
    dbg_assert(tei != 0 && tei != 0xFF);
    memcpy(m_dak[tei], dak, sizeof(m_dak[0]));
}

E_ErrCode secu_nmk2nid(u8 *nmk, u8 security_level, u8 *nid)
{
    E_ErrCode ret;
    u8        nid_offset[NID_SIZE] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00};

    dbg_assert (nmk);
    dbg_assert (nid);
    dbg_assert (security_level <= 2); /* supported security-levels = 0, 1 or 2 */

    /* generate NID offset value (52 bits) from NMK */
    ret = secu_hash(PWD_NMK, nmk, 16, nid_offset);
    if (ret == Success)
    {
        memcpy(nid,nid_offset,NID_SIZE);
        /*
         * combine the NID offset (52 bits) and Security Level (2 bits) together
         * to form the NID value (54 bits)
         *    - Octets[0:5] of NID = octets[0:5] of the 52 Bit Hashed NID offset
         *      (Leftmost octet = Leftmost Octet of 52 Bit Hashed NID Offset)
         *    - Right nibble of rightmost octet of NID = rightmost nibble of the 52 Bit Hashed NID offset
         *    - Left nibble of rightmost octet of NID = Security Level 
         */
        nid[NID_SIZE-1] >>= 4; /* Set the right nibble of rightmost octet of NID = rightmost nibble of the 52 Bit Hashed NID offset*/
        nid[NID_SIZE-1] &= 0x0F; /* Mask the left nibble of rightmost octet of NID... */
        nid[NID_SIZE-1] |= ((security_level << 4) & 0xF0); /* ... and then, insert the Security Level */
    }

    return ret;
}

E_ErrCode secu_npw2nmk(char *npw, u8 *nmk)
{
    E_ErrCode ret;

    dbg_assert (npw);
    dbg_assert (nmk);

    /* generate default NMK key from NPW password */
    ret = secu_hash(PWD_NPW, (u8*)npw, strlen(npw), nmk);

    return ret;
}

bool
secu_get_kbc (cp_secu_t *ctx)
{
    dbg_assert (ctx);

    return ctx->kbc;
}

bool
cp_secu_get_kbc (cp_secu_t *ctx)
{
    dbg_assert (ctx);

    return ctx->kbc;
}

u8
secu_get_eks (cp_secu_t *ctx)
{
    dbg_assert (ctx);

    return ctx->eks;
}

u8
cp_secu_get_eks (cp_secu_t *ctx)
{
    dbg_assert (ctx);

    return ctx->eks;
}