]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/apr-util/crypto/apr_crypto_nss.c
devd.conf(5): Fix a mandoc related issue
[FreeBSD/FreeBSD.git] / contrib / apr-util / crypto / apr_crypto_nss.c
1 /* Licensed to the Apache Software Foundation (ASF) under one or more
2  * contributor license agreements.  See the NOTICE file distributed with
3  * this work for additional information regarding copyright ownership.
4  * The ASF licenses this file to You under the Apache License, Version 2.0
5  * (the "License"); you may not use this file except in compliance with
6  * the License.  You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include "apr_lib.h"
18 #include "apu.h"
19 #include "apu_config.h"
20 #include "apu_errno.h"
21
22 #include <ctype.h>
23 #include <stdlib.h>
24
25 #include "apr_strings.h"
26 #include "apr_time.h"
27 #include "apr_buckets.h"
28
29 #include "apr_crypto_internal.h"
30
31 #if APU_HAVE_CRYPTO
32
33 #include <prerror.h>
34
35 #ifdef HAVE_NSS_NSS_H
36 #include <nss/nss.h>
37 #endif
38 #ifdef HAVE_NSS_H
39 #include <nss.h>
40 #endif
41
42 #ifdef HAVE_NSS_PK11PUB_H
43 #include <nss/pk11pub.h>
44 #endif
45 #ifdef HAVE_PK11PUB_H
46 #include <pk11pub.h>
47 #endif
48
49 struct apr_crypto_t {
50     apr_pool_t *pool;
51     const apr_crypto_driver_t *provider;
52     apu_err_t *result;
53     apr_crypto_config_t *config;
54     apr_hash_t *types;
55     apr_hash_t *modes;
56 };
57
58 struct apr_crypto_config_t {
59        void *opaque;
60 };
61
62 struct apr_crypto_key_t {
63     apr_pool_t *pool;
64     const apr_crypto_driver_t *provider;
65     const apr_crypto_t *f;
66     CK_MECHANISM_TYPE cipherMech;
67     SECOidTag cipherOid;
68     PK11SymKey *symKey;
69     int ivSize;
70     int keyLength;
71 };
72
73 struct apr_crypto_block_t {
74     apr_pool_t *pool;
75     const apr_crypto_driver_t *provider;
76     const apr_crypto_t *f;
77     PK11Context *ctx;
78     apr_crypto_key_t *key;
79     SECItem *secParam;
80     int blockSize;
81 };
82
83 static struct apr_crypto_block_key_type_t key_types[] =
84 {
85 { APR_KEY_3DES_192, 24, 8, 8 },
86 { APR_KEY_AES_128, 16, 16, 16 },
87 { APR_KEY_AES_192, 24, 16, 16 },
88 { APR_KEY_AES_256, 32, 16, 16 } };
89
90 static struct apr_crypto_block_key_mode_t key_modes[] =
91 {
92 { APR_MODE_ECB },
93 { APR_MODE_CBC } };
94
95 /* sufficient space to wrap a key */
96 #define BUFFER_SIZE 128
97
98 /**
99  * Fetch the most recent error from this driver.
100  */
101 static apr_status_t crypto_error(const apu_err_t **result,
102         const apr_crypto_t *f)
103 {
104     *result = f->result;
105     return APR_SUCCESS;
106 }
107
108 /**
109  * Shutdown the crypto library and release resources.
110  *
111  * It is safe to shut down twice.
112  */
113 static apr_status_t crypto_shutdown(void)
114 {
115     if (NSS_IsInitialized()) {
116         SECStatus s = NSS_Shutdown();
117         if (s != SECSuccess) {
118             fprintf(stderr, "NSS failed to shutdown, possible leak: %d: %s",
119                 PR_GetError(), PR_ErrorToName(s));
120             return APR_EINIT;
121         }
122     }
123     return APR_SUCCESS;
124 }
125
126 static apr_status_t crypto_shutdown_helper(void *data)
127 {
128     return crypto_shutdown();
129 }
130
131 /**
132  * Initialise the crypto library and perform one time initialisation.
133  */
134 static apr_status_t crypto_init(apr_pool_t *pool, const char *params,
135         const apu_err_t **result)
136 {
137     SECStatus s;
138     const char *dir = NULL;
139     const char *keyPrefix = NULL;
140     const char *certPrefix = NULL;
141     const char *secmod = NULL;
142     int noinit = 0;
143     PRUint32 flags = 0;
144
145     struct {
146         const char *field;
147         const char *value;
148         int set;
149     } fields[] = {
150         { "dir", NULL, 0 },
151         { "key3", NULL, 0 },
152         { "cert7", NULL, 0 },
153         { "secmod", NULL, 0 },
154         { "noinit", NULL, 0 },
155         { NULL, NULL, 0 }
156     };
157     const char *ptr;
158     size_t klen;
159     char **elts = NULL;
160     char *elt;
161     int i = 0, j;
162     apr_status_t status;
163
164     if (params) {
165         if (APR_SUCCESS != (status = apr_tokenize_to_argv(params, &elts, pool))) {
166             return status;
167         }
168         while ((elt = elts[i])) {
169             ptr = strchr(elt, '=');
170             if (ptr) {
171                 for (klen = ptr - elt; klen && apr_isspace(elt[klen - 1]); --klen)
172                     ;
173                 ptr++;
174             }
175             else {
176                 for (klen = strlen(elt); klen && apr_isspace(elt[klen - 1]); --klen)
177                     ;
178             }
179             elt[klen] = 0;
180
181             for (j = 0; fields[j].field != NULL; ++j) {
182                 if (klen && !strcasecmp(fields[j].field, elt)) {
183                     fields[j].set = 1;
184                     if (ptr) {
185                         fields[j].value = ptr;
186                     }
187                     break;
188                 }
189             }
190
191             i++;
192         }
193         dir = fields[0].value;
194         keyPrefix = fields[1].value;
195         certPrefix = fields[2].value;
196         secmod = fields[3].value;
197         noinit = fields[4].set;
198     }
199
200     /* if we've been asked to bypass, do so here */
201     if (noinit) {
202         return APR_SUCCESS;
203     }
204
205     /* sanity check - we can only initialise NSS once */
206     if (NSS_IsInitialized()) {
207         return APR_EREINIT;
208     }
209
210     if (keyPrefix || certPrefix || secmod) {
211         s = NSS_Initialize(dir, certPrefix, keyPrefix, secmod, flags);
212     }
213     else if (dir) {
214         s = NSS_InitReadWrite(dir);
215     }
216     else {
217         s = NSS_NoDB_Init(NULL);
218     }
219     if (s != SECSuccess) {
220         if (result) {
221             /* Note: all memory must be owned by the caller, in case we're unloaded */
222             apu_err_t *err = apr_pcalloc(pool, sizeof(apu_err_t));
223             err->rc = PR_GetError();
224             err->msg = apr_pstrdup(pool, PR_ErrorToName(s));
225             err->reason = apr_pstrdup(pool, "Error during 'nss' initialisation");
226             *result = err;
227         }
228
229         return APR_ECRYPT;
230     }
231
232     apr_pool_cleanup_register(pool, pool, crypto_shutdown_helper,
233             apr_pool_cleanup_null);
234
235     return APR_SUCCESS;
236
237 }
238
239 /**
240  * @brief Clean encryption / decryption context.
241  * @note After cleanup, a context is free to be reused if necessary.
242  * @param f The context to use.
243  * @return Returns APR_ENOTIMPL if not supported.
244  */
245 static apr_status_t crypto_block_cleanup(apr_crypto_block_t *block)
246 {
247
248     if (block->secParam) {
249         SECITEM_FreeItem(block->secParam, PR_TRUE);
250         block->secParam = NULL;
251     }
252
253     if (block->ctx) {
254         PK11_DestroyContext(block->ctx, PR_TRUE);
255         block->ctx = NULL;
256     }
257
258     return APR_SUCCESS;
259
260 }
261
262 static apr_status_t crypto_block_cleanup_helper(void *data)
263 {
264     apr_crypto_block_t *block = (apr_crypto_block_t *) data;
265     return crypto_block_cleanup(block);
266 }
267
268 static apr_status_t crypto_key_cleanup(void *data)
269 {
270     apr_crypto_key_t *key = data;
271     if (key->symKey) {
272         PK11_FreeSymKey(key->symKey);
273         key->symKey = NULL;
274     }
275     return APR_SUCCESS;
276 }
277 /**
278  * @brief Clean encryption / decryption context.
279  * @note After cleanup, a context is free to be reused if necessary.
280  * @param f The context to use.
281  * @return Returns APR_ENOTIMPL if not supported.
282  */
283 static apr_status_t crypto_cleanup(apr_crypto_t *f)
284 {
285     return APR_SUCCESS;
286 }
287
288 static apr_status_t crypto_cleanup_helper(void *data)
289 {
290     apr_crypto_t *f = (apr_crypto_t *) data;
291     return crypto_cleanup(f);
292 }
293
294 /**
295  * @brief Create a context for supporting encryption. Keys, certificates,
296  *        algorithms and other parameters will be set per context. More than
297  *        one context can be created at one time. A cleanup will be automatically
298  *        registered with the given pool to guarantee a graceful shutdown.
299  * @param f - context pointer will be written here
300  * @param provider - provider to use
301  * @param params - parameter string
302  * @param pool - process pool
303  * @return APR_ENOENGINE when the engine specified does not exist. APR_EINITENGINE
304  * if the engine cannot be initialised.
305  */
306 static apr_status_t crypto_make(apr_crypto_t **ff,
307         const apr_crypto_driver_t *provider, const char *params,
308         apr_pool_t *pool)
309 {
310     apr_crypto_config_t *config = NULL;
311     apr_crypto_t *f;
312
313     f = apr_pcalloc(pool, sizeof(apr_crypto_t));
314     if (!f) {
315         return APR_ENOMEM;
316     }
317     *ff = f;
318     f->pool = pool;
319     f->provider = provider;
320     config = f->config = apr_pcalloc(pool, sizeof(apr_crypto_config_t));
321     if (!config) {
322         return APR_ENOMEM;
323     }
324     f->result = apr_pcalloc(pool, sizeof(apu_err_t));
325     if (!f->result) {
326         return APR_ENOMEM;
327     }
328
329     f->types = apr_hash_make(pool);
330     if (!f->types) {
331         return APR_ENOMEM;
332     }
333     apr_hash_set(f->types, "3des192", APR_HASH_KEY_STRING, &(key_types[0]));
334     apr_hash_set(f->types, "aes128", APR_HASH_KEY_STRING, &(key_types[1]));
335     apr_hash_set(f->types, "aes192", APR_HASH_KEY_STRING, &(key_types[2]));
336     apr_hash_set(f->types, "aes256", APR_HASH_KEY_STRING, &(key_types[3]));
337
338     f->modes = apr_hash_make(pool);
339     if (!f->modes) {
340         return APR_ENOMEM;
341     }
342     apr_hash_set(f->modes, "ecb", APR_HASH_KEY_STRING, &(key_modes[0]));
343     apr_hash_set(f->modes, "cbc", APR_HASH_KEY_STRING, &(key_modes[1]));
344
345     apr_pool_cleanup_register(pool, f, crypto_cleanup_helper,
346             apr_pool_cleanup_null);
347
348     return APR_SUCCESS;
349
350 }
351
352 /**
353  * @brief Get a hash table of key types, keyed by the name of the type against
354  * a pointer to apr_crypto_block_key_type_t.
355  *
356  * @param types - hashtable of key types keyed to constants.
357  * @param f - encryption context
358  * @return APR_SUCCESS for success
359  */
360 static apr_status_t crypto_get_block_key_types(apr_hash_t **types,
361         const apr_crypto_t *f)
362 {
363     *types = f->types;
364     return APR_SUCCESS;
365 }
366
367 /**
368  * @brief Get a hash table of key modes, keyed by the name of the mode against
369  * a pointer to apr_crypto_block_key_mode_t.
370  *
371  * @param modes - hashtable of key modes keyed to constants.
372  * @param f - encryption context
373  * @return APR_SUCCESS for success
374  */
375 static apr_status_t crypto_get_block_key_modes(apr_hash_t **modes,
376         const apr_crypto_t *f)
377 {
378     *modes = f->modes;
379     return APR_SUCCESS;
380 }
381
382 /*
383  * Work out which mechanism to use.
384  */
385 static apr_status_t crypto_cipher_mechanism(apr_crypto_key_t *key,
386         const apr_crypto_block_key_type_e type,
387         const apr_crypto_block_key_mode_e mode, const int doPad)
388 {
389
390     /* decide on what cipher mechanism we will be using */
391     switch (type) {
392
393     case (APR_KEY_3DES_192):
394         if (APR_MODE_CBC == mode) {
395             key->cipherOid = SEC_OID_DES_EDE3_CBC;
396         }
397         else if (APR_MODE_ECB == mode) {
398             return APR_ENOCIPHER;
399             /* No OID for CKM_DES3_ECB; */
400         }
401         key->keyLength = 24;
402         break;
403     case (APR_KEY_AES_128):
404         if (APR_MODE_CBC == mode) {
405             key->cipherOid = SEC_OID_AES_128_CBC;
406         }
407         else {
408             key->cipherOid = SEC_OID_AES_128_ECB;
409         }
410         key->keyLength = 16;
411         break;
412     case (APR_KEY_AES_192):
413         if (APR_MODE_CBC == mode) {
414             key->cipherOid = SEC_OID_AES_192_CBC;
415         }
416         else {
417             key->cipherOid = SEC_OID_AES_192_ECB;
418         }
419         key->keyLength = 24;
420         break;
421     case (APR_KEY_AES_256):
422         if (APR_MODE_CBC == mode) {
423             key->cipherOid = SEC_OID_AES_256_CBC;
424         }
425         else {
426             key->cipherOid = SEC_OID_AES_256_ECB;
427         }
428         key->keyLength = 32;
429         break;
430     default:
431         /* unknown key type, give up */
432         return APR_EKEYTYPE;
433     }
434
435     /* AES_128_CBC --> CKM_AES_CBC --> CKM_AES_CBC_PAD */
436     key->cipherMech = PK11_AlgtagToMechanism(key->cipherOid);
437     if (key->cipherMech == CKM_INVALID_MECHANISM) {
438         return APR_ENOCIPHER;
439     }
440     if (doPad) {
441         CK_MECHANISM_TYPE paddedMech;
442         paddedMech = PK11_GetPadMechanism(key->cipherMech);
443         if (CKM_INVALID_MECHANISM == paddedMech
444                 || key->cipherMech == paddedMech) {
445             return APR_EPADDING;
446         }
447         key->cipherMech = paddedMech;
448     }
449
450     key->ivSize = PK11_GetIVLength(key->cipherMech);
451
452     return APR_SUCCESS;
453 }
454
455 /**
456  * @brief Create a key from the provided secret or passphrase. The key is cleaned
457  *        up when the context is cleaned, and may be reused with multiple encryption
458  *        or decryption operations.
459  * @note If *key is NULL, a apr_crypto_key_t will be created from a pool. If
460  *       *key is not NULL, *key must point at a previously created structure.
461  * @param key The key returned, see note.
462  * @param rec The key record, from which the key will be derived.
463  * @param f The context to use.
464  * @param p The pool to use.
465  * @return Returns APR_ENOKEY if the pass phrase is missing or empty, or if a backend
466  *         error occurred while generating the key. APR_ENOCIPHER if the type or mode
467  *         is not supported by the particular backend. APR_EKEYTYPE if the key type is
468  *         not known. APR_EPADDING if padding was requested but is not supported.
469  *         APR_ENOTIMPL if not implemented.
470  */
471 static apr_status_t crypto_key(apr_crypto_key_t **k,
472         const apr_crypto_key_rec_t *rec, const apr_crypto_t *f, apr_pool_t *p)
473 {
474     apr_status_t rv = APR_SUCCESS;
475     PK11SlotInfo *slot, *tslot;
476     PK11SymKey *tkey;
477     SECItem secretItem;
478     SECItem wrappedItem;
479     SECItem *secParam;
480     PK11Context *ctx;
481     SECStatus s;
482     SECItem passItem;
483     SECItem saltItem;
484     SECAlgorithmID *algid;
485     void *wincx = NULL; /* what is wincx? */
486     apr_crypto_key_t *key;
487     int blockSize;
488     int remainder;
489
490     key = *k;
491     if (!key) {
492         *k = key = apr_pcalloc(p, sizeof *key);
493         if (!key) {
494             return APR_ENOMEM;
495         }
496         apr_pool_cleanup_register(p, key, crypto_key_cleanup,
497                                   apr_pool_cleanup_null);
498     }
499
500     key->f = f;
501     key->provider = f->provider;
502
503     /* decide on what cipher mechanism we will be using */
504     rv = crypto_cipher_mechanism(key, rec->type, rec->mode, rec->pad);
505     if (APR_SUCCESS != rv) {
506         return rv;
507     }
508
509     switch (rec->ktype) {
510
511     case APR_CRYPTO_KTYPE_PASSPHRASE: {
512
513         /* Turn the raw passphrase and salt into SECItems */
514         passItem.data = (unsigned char*) rec->k.passphrase.pass;
515         passItem.len = rec->k.passphrase.passLen;
516         saltItem.data = (unsigned char*) rec->k.passphrase.salt;
517         saltItem.len = rec->k.passphrase.saltLen;
518
519         /* generate the key */
520         /* pbeAlg and cipherAlg are the same. */
521         algid = PK11_CreatePBEV2AlgorithmID(key->cipherOid, key->cipherOid,
522                 SEC_OID_HMAC_SHA1, key->keyLength,
523                 rec->k.passphrase.iterations, &saltItem);
524         if (algid) {
525             slot = PK11_GetBestSlot(key->cipherMech, wincx);
526             if (slot) {
527                 key->symKey = PK11_PBEKeyGen(slot, algid, &passItem, PR_FALSE,
528                         wincx);
529                 PK11_FreeSlot(slot);
530             }
531             SECOID_DestroyAlgorithmID(algid, PR_TRUE);
532         }
533
534         break;
535     }
536
537     case APR_CRYPTO_KTYPE_SECRET: {
538
539         /*
540          * NSS is by default in FIPS mode, which disallows the use of unencrypted
541          * symmetrical keys. As per http://permalink.gmane.org/gmane.comp.mozilla.crypto/7947
542          * we do the following:
543          *
544          * 1. Generate a (temporary) symmetric key in NSS.
545          * 2. Use that symmetric key to encrypt your symmetric key as data.
546          * 3. Unwrap your wrapped symmetric key, using the symmetric key
547          * you generated in Step 1 as the unwrapping key.
548          *
549          * http://permalink.gmane.org/gmane.comp.mozilla.crypto/7947
550          */
551
552         /* generate the key */
553         slot = PK11_GetBestSlot(key->cipherMech, NULL);
554         if (slot) {
555             unsigned char data[BUFFER_SIZE];
556
557             /* sanity check - key correct size? */
558             if (rec->k.secret.secretLen != key->keyLength) {
559                 PK11_FreeSlot(slot);
560                 return APR_EKEYLENGTH;
561             }
562
563             tslot = PK11_GetBestSlot(CKM_AES_ECB, NULL);
564             if (tslot) {
565
566                 /* generate a temporary wrapping key */
567                 tkey = PK11_KeyGen(tslot, CKM_AES_ECB, 0, PK11_GetBestKeyLength(tslot, CKM_AES_ECB), 0);
568
569                 /* prepare the key to wrap */
570                 secretItem.data = (unsigned char *) rec->k.secret.secret;
571                 secretItem.len = rec->k.secret.secretLen;
572
573                 /* ensure our key matches the blocksize */
574                 secParam = PK11_GenerateNewParam(CKM_AES_ECB, tkey);
575                 blockSize = PK11_GetBlockSize(CKM_AES_ECB, secParam);
576                 remainder = rec->k.secret.secretLen % blockSize;
577                 if (remainder) {
578                     secretItem.data =
579                             apr_pcalloc(p, rec->k.secret.secretLen + remainder);
580                     apr_crypto_clear(p, secretItem.data,
581                             rec->k.secret.secretLen);
582                     memcpy(secretItem.data, rec->k.secret.secret,
583                             rec->k.secret.secretLen);
584                     secretItem.len += remainder;
585                 }
586
587                 /* prepare a space for the wrapped key */
588                 wrappedItem.data = data;
589
590                 /* wrap the key */
591                 ctx = PK11_CreateContextBySymKey(CKM_AES_ECB, CKA_ENCRYPT, tkey,
592                         secParam);
593                 if (ctx) {
594                     s = PK11_CipherOp(ctx, wrappedItem.data,
595                             (int *) (&wrappedItem.len), BUFFER_SIZE,
596                             secretItem.data, secretItem.len);
597                     if (s == SECSuccess) {
598
599                         /* unwrap the key again */
600                         key->symKey = PK11_UnwrapSymKeyWithFlags(tkey,
601                                 CKM_AES_ECB, NULL, &wrappedItem,
602                                 key->cipherMech, CKA_ENCRYPT,
603                                 rec->k.secret.secretLen, 0);
604
605                     }
606
607                     PK11_DestroyContext(ctx, PR_TRUE);
608                 }
609
610                 /* clean up */
611                 SECITEM_FreeItem(secParam, PR_TRUE);
612                 PK11_FreeSymKey(tkey);
613                 PK11_FreeSlot(tslot);
614
615             }
616
617             PK11_FreeSlot(slot);
618         }
619
620         break;
621     }
622
623     default: {
624
625         return APR_ENOKEY;
626
627     }
628     }
629
630     /* sanity check? */
631     if (!key->symKey) {
632         PRErrorCode perr = PORT_GetError();
633         if (perr) {
634             f->result->rc = perr;
635             f->result->msg = PR_ErrorToName(perr);
636             rv = APR_ENOKEY;
637         }
638     }
639
640     return rv;
641 }
642
643 /**
644  * @brief Create a key from the given passphrase. By default, the PBKDF2
645  *        algorithm is used to generate the key from the passphrase. It is expected
646  *        that the same pass phrase will generate the same key, regardless of the
647  *        backend crypto platform used. The key is cleaned up when the context
648  *        is cleaned, and may be reused with multiple encryption or decryption
649  *        operations.
650  * @note If *key is NULL, a apr_crypto_key_t will be created from a pool. If
651  *       *key is not NULL, *key must point at a previously created structure.
652  * @param key The key returned, see note.
653  * @param ivSize The size of the initialisation vector will be returned, based
654  *               on whether an IV is relevant for this type of crypto.
655  * @param pass The passphrase to use.
656  * @param passLen The passphrase length in bytes
657  * @param salt The salt to use.
658  * @param saltLen The salt length in bytes
659  * @param type 3DES_192, AES_128, AES_192, AES_256.
660  * @param mode Electronic Code Book / Cipher Block Chaining.
661  * @param doPad Pad if necessary.
662  * @param iterations Iteration count
663  * @param f The context to use.
664  * @param p The pool to use.
665  * @return Returns APR_ENOKEY if the pass phrase is missing or empty, or if a backend
666  *         error occurred while generating the key. APR_ENOCIPHER if the type or mode
667  *         is not supported by the particular backend. APR_EKEYTYPE if the key type is
668  *         not known. APR_EPADDING if padding was requested but is not supported.
669  *         APR_ENOTIMPL if not implemented.
670  */
671 static apr_status_t crypto_passphrase(apr_crypto_key_t **k, apr_size_t *ivSize,
672         const char *pass, apr_size_t passLen, const unsigned char * salt,
673         apr_size_t saltLen, const apr_crypto_block_key_type_e type,
674         const apr_crypto_block_key_mode_e mode, const int doPad,
675         const int iterations, const apr_crypto_t *f, apr_pool_t *p)
676 {
677     apr_status_t rv = APR_SUCCESS;
678     PK11SlotInfo * slot;
679     SECItem passItem;
680     SECItem saltItem;
681     SECAlgorithmID *algid;
682     void *wincx = NULL; /* what is wincx? */
683     apr_crypto_key_t *key = *k;
684
685     if (!key) {
686         *k = key = apr_pcalloc(p, sizeof *key);
687         if (!key) {
688             return APR_ENOMEM;
689         }
690         apr_pool_cleanup_register(p, key, crypto_key_cleanup,
691                                   apr_pool_cleanup_null);
692     }
693
694     key->f = f;
695     key->provider = f->provider;
696
697     /* decide on what cipher mechanism we will be using */
698     rv = crypto_cipher_mechanism(key, type, mode, doPad);
699     if (APR_SUCCESS != rv) {
700         return rv;
701     }
702
703     /* Turn the raw passphrase and salt into SECItems */
704     passItem.data = (unsigned char*) pass;
705     passItem.len = passLen;
706     saltItem.data = (unsigned char*) salt;
707     saltItem.len = saltLen;
708
709     /* generate the key */
710     /* pbeAlg and cipherAlg are the same. */
711     algid = PK11_CreatePBEV2AlgorithmID(key->cipherOid, key->cipherOid,
712             SEC_OID_HMAC_SHA1, key->keyLength, iterations, &saltItem);
713     if (algid) {
714         slot = PK11_GetBestSlot(key->cipherMech, wincx);
715         if (slot) {
716             key->symKey = PK11_PBEKeyGen(slot, algid, &passItem, PR_FALSE,
717                     wincx);
718             PK11_FreeSlot(slot);
719         }
720         SECOID_DestroyAlgorithmID(algid, PR_TRUE);
721     }
722
723     /* sanity check? */
724     if (!key->symKey) {
725         PRErrorCode perr = PORT_GetError();
726         if (perr) {
727             f->result->rc = perr;
728             f->result->msg = PR_ErrorToName(perr);
729             rv = APR_ENOKEY;
730         }
731     }
732
733     if (ivSize) {
734         *ivSize = key->ivSize;
735     }
736
737     return rv;
738 }
739
740 /**
741  * @brief Initialise a context for encrypting arbitrary data using the given key.
742  * @note If *ctx is NULL, a apr_crypto_block_t will be created from a pool. If
743  *       *ctx is not NULL, *ctx must point at a previously created structure.
744  * @param ctx The block context returned, see note.
745  * @param iv Optional initialisation vector. If the buffer pointed to is NULL,
746  *           an IV will be created at random, in space allocated from the pool.
747  *           If the buffer pointed to is not NULL, the IV in the buffer will be
748  *           used.
749  * @param key The key structure.
750  * @param blockSize The block size of the cipher.
751  * @param p The pool to use.
752  * @return Returns APR_ENOIV if an initialisation vector is required but not specified.
753  *         Returns APR_EINIT if the backend failed to initialise the context. Returns
754  *         APR_ENOTIMPL if not implemented.
755  */
756 static apr_status_t crypto_block_encrypt_init(apr_crypto_block_t **ctx,
757         const unsigned char **iv, const apr_crypto_key_t *key,
758         apr_size_t *blockSize, apr_pool_t *p)
759 {
760     PRErrorCode perr;
761     SECItem ivItem;
762     unsigned char * usedIv;
763     apr_crypto_block_t *block = *ctx;
764     if (!block) {
765         *ctx = block = apr_pcalloc(p, sizeof(apr_crypto_block_t));
766     }
767     if (!block) {
768         return APR_ENOMEM;
769     }
770     block->f = key->f;
771     block->pool = p;
772     block->provider = key->provider;
773
774     apr_pool_cleanup_register(p, block, crypto_block_cleanup_helper,
775             apr_pool_cleanup_null);
776
777     if (key->ivSize) {
778         if (iv == NULL) {
779             return APR_ENOIV;
780         }
781         if (*iv == NULL) {
782             SECStatus s;
783             usedIv = apr_pcalloc(p, key->ivSize);
784             if (!usedIv) {
785                 return APR_ENOMEM;
786             }
787             apr_crypto_clear(p, usedIv, key->ivSize);
788             s = PK11_GenerateRandom(usedIv, key->ivSize);
789             if (s != SECSuccess) {
790                 return APR_ENOIV;
791             }
792             *iv = usedIv;
793         }
794         else {
795             usedIv = (unsigned char *) *iv;
796         }
797         ivItem.data = usedIv;
798         ivItem.len = key->ivSize;
799         block->secParam = PK11_ParamFromIV(key->cipherMech, &ivItem);
800     }
801     else {
802         block->secParam = PK11_GenerateNewParam(key->cipherMech, key->symKey);
803     }
804     block->blockSize = PK11_GetBlockSize(key->cipherMech, block->secParam);
805     block->ctx = PK11_CreateContextBySymKey(key->cipherMech, CKA_ENCRYPT,
806             key->symKey, block->secParam);
807
808     /* did an error occur? */
809     perr = PORT_GetError();
810     if (perr || !block->ctx) {
811         key->f->result->rc = perr;
812         key->f->result->msg = PR_ErrorToName(perr);
813         return APR_EINIT;
814     }
815
816     if (blockSize) {
817         *blockSize = PK11_GetBlockSize(key->cipherMech, block->secParam);
818     }
819
820     return APR_SUCCESS;
821
822 }
823
824 /**
825  * @brief Encrypt data provided by in, write it to out.
826  * @note The number of bytes written will be written to outlen. If
827  *       out is NULL, outlen will contain the maximum size of the
828  *       buffer needed to hold the data, including any data
829  *       generated by apr_crypto_block_encrypt_finish below. If *out points
830  *       to NULL, a buffer sufficiently large will be created from
831  *       the pool provided. If *out points to a not-NULL value, this
832  *       value will be used as a buffer instead.
833  * @param out Address of a buffer to which data will be written,
834  *        see note.
835  * @param outlen Length of the output will be written here.
836  * @param in Address of the buffer to read.
837  * @param inlen Length of the buffer to read.
838  * @param ctx The block context to use.
839  * @return APR_ECRYPT if an error occurred. Returns APR_ENOTIMPL if
840  *         not implemented.
841  */
842 static apr_status_t crypto_block_encrypt(unsigned char **out,
843         apr_size_t *outlen, const unsigned char *in, apr_size_t inlen,
844         apr_crypto_block_t *block)
845 {
846
847     unsigned char *buffer;
848     int outl = (int) *outlen;
849     SECStatus s;
850     if (!out) {
851         *outlen = inlen + block->blockSize;
852         return APR_SUCCESS;
853     }
854     if (!*out) {
855         buffer = apr_palloc(block->pool, inlen + block->blockSize);
856         if (!buffer) {
857             return APR_ENOMEM;
858         }
859         apr_crypto_clear(block->pool, buffer, inlen + block->blockSize);
860         *out = buffer;
861     }
862
863     s = PK11_CipherOp(block->ctx, *out, &outl, inlen, (unsigned char*) in,
864             inlen);
865     if (s != SECSuccess) {
866         PRErrorCode perr = PORT_GetError();
867         if (perr) {
868             block->f->result->rc = perr;
869             block->f->result->msg = PR_ErrorToName(perr);
870         }
871         return APR_ECRYPT;
872     }
873     *outlen = outl;
874
875     return APR_SUCCESS;
876
877 }
878
879 /**
880  * @brief Encrypt final data block, write it to out.
881  * @note If necessary the final block will be written out after being
882  *       padded. Typically the final block will be written to the
883  *       same buffer used by apr_crypto_block_encrypt, offset by the
884  *       number of bytes returned as actually written by the
885  *       apr_crypto_block_encrypt() call. After this call, the context
886  *       is cleaned and can be reused by apr_crypto_block_encrypt_init().
887  * @param out Address of a buffer to which data will be written. This
888  *            buffer must already exist, and is usually the same
889  *            buffer used by apr_evp_crypt(). See note.
890  * @param outlen Length of the output will be written here.
891  * @param ctx The block context to use.
892  * @return APR_ECRYPT if an error occurred.
893  * @return APR_EPADDING if padding was enabled and the block was incorrectly
894  *         formatted.
895  * @return APR_ENOTIMPL if not implemented.
896  */
897 static apr_status_t crypto_block_encrypt_finish(unsigned char *out,
898         apr_size_t *outlen, apr_crypto_block_t *block)
899 {
900
901     apr_status_t rv = APR_SUCCESS;
902     unsigned int outl = *outlen;
903
904     SECStatus s = PK11_DigestFinal(block->ctx, out, &outl, block->blockSize);
905     *outlen = outl;
906
907     if (s != SECSuccess) {
908         PRErrorCode perr = PORT_GetError();
909         if (perr) {
910             block->f->result->rc = perr;
911             block->f->result->msg = PR_ErrorToName(perr);
912         }
913         rv = APR_ECRYPT;
914     }
915     crypto_block_cleanup(block);
916
917     return rv;
918
919 }
920
921 /**
922  * @brief Initialise a context for decrypting arbitrary data using the given key.
923  * @note If *ctx is NULL, a apr_crypto_block_t will be created from a pool. If
924  *       *ctx is not NULL, *ctx must point at a previously created structure.
925  * @param ctx The block context returned, see note.
926  * @param blockSize The block size of the cipher.
927  * @param iv Optional initialisation vector. If the buffer pointed to is NULL,
928  *           an IV will be created at random, in space allocated from the pool.
929  *           If the buffer is not NULL, the IV in the buffer will be used.
930  * @param key The key structure.
931  * @param p The pool to use.
932  * @return Returns APR_ENOIV if an initialisation vector is required but not specified.
933  *         Returns APR_EINIT if the backend failed to initialise the context. Returns
934  *         APR_ENOTIMPL if not implemented.
935  */
936 static apr_status_t crypto_block_decrypt_init(apr_crypto_block_t **ctx,
937         apr_size_t *blockSize, const unsigned char *iv,
938         const apr_crypto_key_t *key, apr_pool_t *p)
939 {
940     PRErrorCode perr;
941     apr_crypto_block_t *block = *ctx;
942     if (!block) {
943         *ctx = block = apr_pcalloc(p, sizeof(apr_crypto_block_t));
944     }
945     if (!block) {
946         return APR_ENOMEM;
947     }
948     block->f = key->f;
949     block->pool = p;
950     block->provider = key->provider;
951
952     apr_pool_cleanup_register(p, block, crypto_block_cleanup_helper,
953             apr_pool_cleanup_null);
954
955     if (key->ivSize) {
956         SECItem ivItem;
957         if (iv == NULL) {
958             return APR_ENOIV; /* Cannot initialise without an IV */
959         }
960         ivItem.data = (unsigned char*) iv;
961         ivItem.len = key->ivSize;
962         block->secParam = PK11_ParamFromIV(key->cipherMech, &ivItem);
963     }
964     else {
965         block->secParam = PK11_GenerateNewParam(key->cipherMech, key->symKey);
966     }
967     block->blockSize = PK11_GetBlockSize(key->cipherMech, block->secParam);
968     block->ctx = PK11_CreateContextBySymKey(key->cipherMech, CKA_DECRYPT,
969             key->symKey, block->secParam);
970
971     /* did an error occur? */
972     perr = PORT_GetError();
973     if (perr || !block->ctx) {
974         key->f->result->rc = perr;
975         key->f->result->msg = PR_ErrorToName(perr);
976         return APR_EINIT;
977     }
978
979     if (blockSize) {
980         *blockSize = PK11_GetBlockSize(key->cipherMech, block->secParam);
981     }
982
983     return APR_SUCCESS;
984
985 }
986
987 /**
988  * @brief Decrypt data provided by in, write it to out.
989  * @note The number of bytes written will be written to outlen. If
990  *       out is NULL, outlen will contain the maximum size of the
991  *       buffer needed to hold the data, including any data
992  *       generated by apr_crypto_block_decrypt_finish below. If *out points
993  *       to NULL, a buffer sufficiently large will be created from
994  *       the pool provided. If *out points to a not-NULL value, this
995  *       value will be used as a buffer instead.
996  * @param out Address of a buffer to which data will be written,
997  *        see note.
998  * @param outlen Length of the output will be written here.
999  * @param in Address of the buffer to read.
1000  * @param inlen Length of the buffer to read.
1001  * @param ctx The block context to use.
1002  * @return APR_ECRYPT if an error occurred. Returns APR_ENOTIMPL if
1003  *         not implemented.
1004  */
1005 static apr_status_t crypto_block_decrypt(unsigned char **out,
1006         apr_size_t *outlen, const unsigned char *in, apr_size_t inlen,
1007         apr_crypto_block_t *block)
1008 {
1009
1010     unsigned char *buffer;
1011     int outl = (int) *outlen;
1012     SECStatus s;
1013     if (!out) {
1014         *outlen = inlen + block->blockSize;
1015         return APR_SUCCESS;
1016     }
1017     if (!*out) {
1018         buffer = apr_palloc(block->pool, inlen + block->blockSize);
1019         if (!buffer) {
1020             return APR_ENOMEM;
1021         }
1022         apr_crypto_clear(block->pool, buffer, inlen + block->blockSize);
1023         *out = buffer;
1024     }
1025
1026     s = PK11_CipherOp(block->ctx, *out, &outl, inlen, (unsigned char*) in,
1027             inlen);
1028     if (s != SECSuccess) {
1029         PRErrorCode perr = PORT_GetError();
1030         if (perr) {
1031             block->f->result->rc = perr;
1032             block->f->result->msg = PR_ErrorToName(perr);
1033         }
1034         return APR_ECRYPT;
1035     }
1036     *outlen = outl;
1037
1038     return APR_SUCCESS;
1039
1040 }
1041
1042 /**
1043  * @brief Decrypt final data block, write it to out.
1044  * @note If necessary the final block will be written out after being
1045  *       padded. Typically the final block will be written to the
1046  *       same buffer used by apr_crypto_block_decrypt, offset by the
1047  *       number of bytes returned as actually written by the
1048  *       apr_crypto_block_decrypt() call. After this call, the context
1049  *       is cleaned and can be reused by apr_crypto_block_decrypt_init().
1050  * @param out Address of a buffer to which data will be written. This
1051  *            buffer must already exist, and is usually the same
1052  *            buffer used by apr_evp_crypt(). See note.
1053  * @param outlen Length of the output will be written here.
1054  * @param ctx The block context to use.
1055  * @return APR_ECRYPT if an error occurred.
1056  * @return APR_EPADDING if padding was enabled and the block was incorrectly
1057  *         formatted.
1058  * @return APR_ENOTIMPL if not implemented.
1059  */
1060 static apr_status_t crypto_block_decrypt_finish(unsigned char *out,
1061         apr_size_t *outlen, apr_crypto_block_t *block)
1062 {
1063
1064     apr_status_t rv = APR_SUCCESS;
1065     unsigned int outl = *outlen;
1066
1067     SECStatus s = PK11_DigestFinal(block->ctx, out, &outl, block->blockSize);
1068     *outlen = outl;
1069
1070     if (s != SECSuccess) {
1071         PRErrorCode perr = PORT_GetError();
1072         if (perr) {
1073             block->f->result->rc = perr;
1074             block->f->result->msg = PR_ErrorToName(perr);
1075         }
1076         rv = APR_ECRYPT;
1077     }
1078     crypto_block_cleanup(block);
1079
1080     return rv;
1081
1082 }
1083
1084 /**
1085  * NSS module.
1086  */
1087 APU_MODULE_DECLARE_DATA const apr_crypto_driver_t apr_crypto_nss_driver = {
1088     "nss", crypto_init, crypto_make, crypto_get_block_key_types,
1089     crypto_get_block_key_modes, crypto_passphrase,
1090     crypto_block_encrypt_init, crypto_block_encrypt,
1091     crypto_block_encrypt_finish, crypto_block_decrypt_init,
1092     crypto_block_decrypt, crypto_block_decrypt_finish,
1093     crypto_block_cleanup, crypto_cleanup, crypto_shutdown, crypto_error,
1094     crypto_key
1095 };
1096
1097 #endif