first batch of license fixes (boring)
[oweals/gnunet.git] / src / util / crypto_kdf.c
1 /*
2      This file is part of GNUnet.
3      Copyright (C) 2010 GNUnet e.V.
4
5      GNUnet is free software: you can redistribute it and/or modify it
6      under the terms of the GNU General Public License as published
7      by the Free Software Foundation, either version 3 of the License,
8      or (at your option) any later version.
9
10      GNUnet is distributed in the hope that it will be useful, but
11      WITHOUT ANY WARRANTY; without even the implied warranty of
12      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13      Affero General Public License for more details.
14 */
15
16 /**
17  * @file src/util/crypto_kdf.c
18  * @brief Key derivation
19  * @author Nils Durner
20  * @author Jeffrey Burdges <burdges@gnunet.org>
21  */
22
23 #include <gcrypt.h>
24
25 #include "platform.h"
26 #include "gnunet_crypto_lib.h"
27
28 #define LOG(kind,...) GNUNET_log_from (kind, "util-crypto-kdf", __VA_ARGS__)
29
30 /**
31  * @brief Derive key
32  * @param result buffer for the derived key, allocated by caller
33  * @param out_len desired length of the derived key
34  * @param xts salt
35  * @param xts_len length of @a xts
36  * @param skm source key material
37  * @param skm_len length of @a skm
38  * @param argp va_list of void * & size_t pairs for context chunks
39  * @return #GNUNET_YES on success
40  */
41 int
42 GNUNET_CRYPTO_kdf_v (void *result,
43                      size_t out_len,
44                      const void *xts,
45                      size_t xts_len,
46                      const void *skm,
47                      size_t skm_len,
48                      va_list argp)
49 {
50   /*
51    * "Finally, we point out to a particularly advantageous instantiation using
52    * HMAC-SHA512 as XTR and HMAC-SHA256 in PRF* (in which case the output from SHA-512 is
53    * truncated to 256 bits). This makes sense in two ways: First, the extraction part is where we need a
54    * stronger hash function due to the unconventional demand from the hash function in the extraction
55    * setting. Second, as shown in Section 6, using HMAC with a truncated output as an extractor
56    * allows to prove the security of HKDF under considerably weaker assumptions on the underlying
57    * hash function."
58    *
59    * http://eprint.iacr.org/2010/264
60    */
61
62   return GNUNET_CRYPTO_hkdf_v (result,
63                                out_len,
64                                GCRY_MD_SHA512,
65                                GCRY_MD_SHA256,
66                                xts,
67                                xts_len,
68                                skm,
69                                skm_len,
70                                argp);
71 }
72
73
74 /**
75  * @brief Derive key
76  * @param result buffer for the derived key, allocated by caller
77  * @param out_len desired length of the derived key
78  * @param xts salt
79  * @param xts_len length of @a xts
80  * @param skm source key material
81  * @param skm_len length of @a skm
82  * @param ... void * & size_t pairs for context chunks
83  * @return #GNUNET_YES on success
84  */
85 int
86 GNUNET_CRYPTO_kdf (void *result,
87                    size_t out_len,
88                    const void *xts,
89                    size_t xts_len,
90                    const void *skm,
91                    size_t skm_len, ...)
92 {
93   va_list argp;
94   int ret;
95
96   va_start (argp, skm_len);
97   ret = GNUNET_CRYPTO_kdf_v (result,
98                              out_len,
99                              xts,
100                              xts_len,
101                              skm,
102                              skm_len,
103                              argp);
104   va_end (argp);
105
106   return ret;
107 }
108
109
110 /**
111  * Deterministically generate a pseudo-random number uniformly from the
112  * integers modulo a libgcrypt mpi.
113  *
114  * @param[out] r MPI value set to the FDH
115  * @param n MPI to work modulo
116  * @param xts salt
117  * @param xts_len length of @a xts
118  * @param skm source key material
119  * @param skm_len length of @a skm
120  * @param ctx context string
121  */
122 void
123 GNUNET_CRYPTO_kdf_mod_mpi (gcry_mpi_t *r,
124                            gcry_mpi_t n,
125                            const void *xts, size_t xts_len,
126                            const void *skm, size_t skm_len,
127                            const char *ctx)
128 {
129   gcry_error_t rc;
130   unsigned int nbits;
131   size_t rsize;
132   unsigned int ctr;
133
134   nbits = gcry_mpi_get_nbits (n);
135   /* GNUNET_assert (nbits > 512); */
136
137   ctr = 0;
138   while (1)
139   {
140     /* Ain't clear if n is always divisible by 8 */
141     uint8_t buf[ (nbits-1)/8 + 1 ];
142
143     rc = GNUNET_CRYPTO_kdf (buf,
144                             sizeof (buf),
145                             xts, xts_len,
146                             skm, skm_len,
147                             ctx, strlen(ctx),
148                             &ctr, sizeof(ctr),
149                             NULL, 0);
150     GNUNET_assert (GNUNET_YES == rc);
151
152     rc = gcry_mpi_scan (r,
153                         GCRYMPI_FMT_USG,
154                         (const unsigned char *) buf,
155                         sizeof (buf),
156                         &rsize);
157     GNUNET_assert (0 == rc);  /* Allocation erro? */
158
159     gcry_mpi_clear_highbit (*r, nbits);
160     GNUNET_assert( 0 == gcry_mpi_test_bit (*r, nbits) );
161     ++ctr;
162     /* We reject this FDH if either *r > n and retry with another ctr */
163     if (0 > gcry_mpi_cmp(*r, n))
164       break;
165     gcry_mpi_release (*r);
166   }
167 }
168
169 /* end of crypto_kdf.c */