"Fossies" - the Fresh Open Source Software Archive

Member "cryptsetup-2.4.3/lib/crypto_backend/crypto_nss.c" (13 Jan 2022, 8515 Bytes) of package /linux/misc/cryptsetup-2.4.3.tar.xz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "crypto_nss.c" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 2.4.0_vs_2.4.1.

    1 /*
    2  * NSS crypto backend implementation
    3  *
    4  * Copyright (C) 2010-2021 Red Hat, Inc. All rights reserved.
    5  * Copyright (C) 2010-2021 Milan Broz
    6  *
    7  * This file is free software; you can redistribute it and/or
    8  * modify it under the terms of the GNU Lesser General Public
    9  * License as published by the Free Software Foundation; either
   10  * version 2.1 of the License, or (at your option) any later version.
   11  *
   12  * This file is distributed in the hope that it will be useful,
   13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
   14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   15  * Lesser General Public License for more details.
   16  *
   17  * You should have received a copy of the GNU Lesser General Public
   18  * License along with this file; if not, write to the Free Software
   19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
   20  */
   21 
   22 #include <string.h>
   23 #include <errno.h>
   24 #include <nss.h>
   25 #include <pk11pub.h>
   26 #include "crypto_backend_internal.h"
   27 
   28 #define CONST_CAST(x) (x)(uintptr_t)
   29 
   30 static int crypto_backend_initialised = 0;
   31 static char version[64];
   32 
   33 struct hash_alg {
   34     const char *name;
   35     SECOidTag oid;
   36     CK_MECHANISM_TYPE ck_type;
   37     int length;
   38     unsigned int block_length;
   39 };
   40 
   41 static struct hash_alg hash_algs[] = {
   42     { "sha1",   SEC_OID_SHA1,   CKM_SHA_1_HMAC,  20,  64 },
   43     { "sha256", SEC_OID_SHA256, CKM_SHA256_HMAC, 32,  64 },
   44     { "sha384", SEC_OID_SHA384, CKM_SHA384_HMAC, 48, 128 },
   45     { "sha512", SEC_OID_SHA512, CKM_SHA512_HMAC, 64, 128 },
   46 //  { "ripemd160", SEC_OID_RIPEMD160, CKM_RIPEMD160_HMAC, 20, 64 },
   47     { NULL, 0, 0, 0 }
   48 };
   49 
   50 struct crypt_hash {
   51     PK11Context *md;
   52     const struct hash_alg *hash;
   53 };
   54 
   55 struct crypt_hmac {
   56     PK11Context *md;
   57     PK11SymKey *key;
   58     PK11SlotInfo *slot;
   59     const struct hash_alg *hash;
   60 };
   61 
   62 struct crypt_cipher {
   63     struct crypt_cipher_kernel ck;
   64 };
   65 
   66 static struct hash_alg *_get_alg(const char *name)
   67 {
   68     int i = 0;
   69 
   70     while (name && hash_algs[i].name) {
   71         if (!strcmp(name, hash_algs[i].name))
   72             return &hash_algs[i];
   73         i++;
   74     }
   75     return NULL;
   76 }
   77 
   78 int crypt_backend_init(bool fips __attribute__((unused)))
   79 {
   80     int r;
   81 
   82     if (crypto_backend_initialised)
   83         return 0;
   84 
   85     if (NSS_NoDB_Init(".") != SECSuccess)
   86         return -EINVAL;
   87 
   88 #if HAVE_DECL_NSS_GETVERSION
   89     r = snprintf(version, sizeof(version), "NSS %s", NSS_GetVersion());
   90 #else
   91     r = snprintf(version, sizeof(version), "NSS");
   92 #endif
   93     if (r < 0 || (size_t)r >= sizeof(version))
   94         return -EINVAL;
   95 
   96     crypto_backend_initialised = 1;
   97     return 0;
   98 }
   99 
  100 void crypt_backend_destroy(void)
  101 {
  102     crypto_backend_initialised = 0;
  103 }
  104 
  105 uint32_t crypt_backend_flags(void)
  106 {
  107     return 0;
  108 }
  109 
  110 const char *crypt_backend_version(void)
  111 {
  112     return crypto_backend_initialised ? version : "";
  113 }
  114 
  115 /* HASH */
  116 int crypt_hash_size(const char *name)
  117 {
  118     struct hash_alg *ha = _get_alg(name);
  119 
  120     return ha ? ha->length : -EINVAL;
  121 }
  122 
  123 int crypt_hash_init(struct crypt_hash **ctx, const char *name)
  124 {
  125     struct crypt_hash *h;
  126 
  127     h = malloc(sizeof(*h));
  128     if (!h)
  129         return -ENOMEM;
  130 
  131     h->hash = _get_alg(name);
  132     if (!h->hash) {
  133         free(h);
  134         return -EINVAL;
  135     }
  136 
  137     h->md = PK11_CreateDigestContext(h->hash->oid);
  138     if (!h->md) {
  139         free(h);
  140         return -EINVAL;
  141     }
  142 
  143     if (PK11_DigestBegin(h->md) != SECSuccess) {
  144         PK11_DestroyContext(h->md, PR_TRUE);
  145         free(h);
  146         return -EINVAL;
  147     }
  148 
  149     *ctx = h;
  150     return 0;
  151 }
  152 
  153 static int crypt_hash_restart(struct crypt_hash *ctx)
  154 {
  155     if (PK11_DigestBegin(ctx->md) != SECSuccess)
  156         return -EINVAL;
  157 
  158     return 0;
  159 }
  160 
  161 int crypt_hash_write(struct crypt_hash *ctx, const char *buffer, size_t length)
  162 {
  163     if (PK11_DigestOp(ctx->md, CONST_CAST(unsigned char *)buffer, length) != SECSuccess)
  164         return -EINVAL;
  165 
  166     return 0;
  167 }
  168 
  169 int crypt_hash_final(struct crypt_hash *ctx, char *buffer, size_t length)
  170 {
  171     unsigned char tmp[64];
  172     unsigned int tmp_len;
  173 
  174     if (length > (size_t)ctx->hash->length)
  175         return -EINVAL;
  176 
  177     if (PK11_DigestFinal(ctx->md, tmp, &tmp_len, length) != SECSuccess)
  178         return -EINVAL;
  179 
  180     memcpy(buffer, tmp, length);
  181     crypt_backend_memzero(tmp, sizeof(tmp));
  182 
  183     if (tmp_len < length)
  184         return -EINVAL;
  185 
  186     if (crypt_hash_restart(ctx))
  187         return -EINVAL;
  188 
  189     return 0;
  190 }
  191 
  192 void crypt_hash_destroy(struct crypt_hash *ctx)
  193 {
  194     PK11_DestroyContext(ctx->md, PR_TRUE);
  195     memset(ctx, 0, sizeof(*ctx));
  196     free(ctx);
  197 }
  198 
  199 /* HMAC */
  200 int crypt_hmac_size(const char *name)
  201 {
  202     return crypt_hash_size(name);
  203 }
  204 
  205 int crypt_hmac_init(struct crypt_hmac **ctx, const char *name,
  206             const void *key, size_t key_length)
  207 {
  208     struct crypt_hmac *h;
  209     SECItem keyItem;
  210     SECItem noParams;
  211 
  212     keyItem.type = siBuffer;
  213     keyItem.data = CONST_CAST(unsigned char *)key;
  214     keyItem.len = (int)key_length;
  215 
  216     noParams.type = siBuffer;
  217     noParams.data = 0;
  218     noParams.len = 0;
  219 
  220     h = malloc(sizeof(*h));
  221     if (!h)
  222         return -ENOMEM;
  223     memset(ctx, 0, sizeof(*ctx));
  224 
  225 
  226     h->hash = _get_alg(name);
  227     if (!h->hash)
  228         goto err;
  229 
  230     h->slot = PK11_GetInternalKeySlot();
  231     if (!h->slot)
  232         goto err;
  233 
  234     h->key = PK11_ImportSymKey(h->slot, h->hash->ck_type, PK11_OriginUnwrap,
  235                    CKA_SIGN,  &keyItem, NULL);
  236     if (!h->key)
  237         goto err;
  238 
  239     h->md = PK11_CreateContextBySymKey(h->hash->ck_type, CKA_SIGN, h->key,
  240                        &noParams);
  241     if (!h->md)
  242         goto err;
  243 
  244     if (PK11_DigestBegin(h->md) != SECSuccess)
  245         goto err;
  246 
  247     *ctx = h;
  248     return 0;
  249 err:
  250     crypt_hmac_destroy(h);
  251     return -EINVAL;
  252 }
  253 
  254 static int crypt_hmac_restart(struct crypt_hmac *ctx)
  255 {
  256     if (PK11_DigestBegin(ctx->md) != SECSuccess)
  257         return -EINVAL;
  258 
  259     return 0;
  260 }
  261 
  262 int crypt_hmac_write(struct crypt_hmac *ctx, const char *buffer, size_t length)
  263 {
  264     if (PK11_DigestOp(ctx->md, CONST_CAST(unsigned char *)buffer, length) != SECSuccess)
  265         return -EINVAL;
  266 
  267     return 0;
  268 }
  269 
  270 int crypt_hmac_final(struct crypt_hmac *ctx, char *buffer, size_t length)
  271 {
  272     unsigned char tmp[64];
  273     unsigned int tmp_len;
  274 
  275     if (length > (size_t)ctx->hash->length)
  276         return -EINVAL;
  277 
  278     if (PK11_DigestFinal(ctx->md, tmp, &tmp_len, length) != SECSuccess)
  279         return -EINVAL;
  280 
  281     memcpy(buffer, tmp, length);
  282     crypt_backend_memzero(tmp, sizeof(tmp));
  283 
  284     if (tmp_len < length)
  285         return -EINVAL;
  286 
  287     if (crypt_hmac_restart(ctx))
  288         return -EINVAL;
  289 
  290     return 0;
  291 }
  292 
  293 void crypt_hmac_destroy(struct crypt_hmac *ctx)
  294 {
  295     if (ctx->key)
  296         PK11_FreeSymKey(ctx->key);
  297     if (ctx->slot)
  298         PK11_FreeSlot(ctx->slot);
  299     if (ctx->md)
  300         PK11_DestroyContext(ctx->md, PR_TRUE);
  301     memset(ctx, 0, sizeof(*ctx));
  302     free(ctx);
  303 }
  304 
  305 /* RNG */
  306 int crypt_backend_rng(char *buffer, size_t length, int quality __attribute__((unused)), int fips)
  307 {
  308     if (fips)
  309         return -EINVAL;
  310 
  311     if (PK11_GenerateRandom((unsigned char *)buffer, length) != SECSuccess)
  312         return -EINVAL;
  313 
  314     return 0;
  315 }
  316 
  317 /* PBKDF */
  318 int crypt_pbkdf(const char *kdf, const char *hash,
  319         const char *password, size_t password_length,
  320         const char *salt, size_t salt_length,
  321         char *key, size_t key_length,
  322         uint32_t iterations, uint32_t memory, uint32_t parallel)
  323 {
  324     struct hash_alg *ha;
  325 
  326     if (!kdf)
  327         return -EINVAL;
  328 
  329     if (!strcmp(kdf, "pbkdf2")) {
  330         ha = _get_alg(hash);
  331         if (!ha)
  332             return -EINVAL;
  333 
  334         return pkcs5_pbkdf2(hash, password, password_length, salt, salt_length,
  335                     iterations, key_length, key, ha->block_length);
  336     } else if (!strncmp(kdf, "argon2", 6)) {
  337         return argon2(kdf, password, password_length, salt, salt_length,
  338                   key, key_length, iterations, memory, parallel);
  339     }
  340 
  341     return -EINVAL;
  342 }
  343 
  344 /* Block ciphers */
  345 int crypt_cipher_init(struct crypt_cipher **ctx, const char *name,
  346             const char *mode, const void *key, size_t key_length)
  347 {
  348     struct crypt_cipher *h;
  349     int r;
  350 
  351     h = malloc(sizeof(*h));
  352     if (!h)
  353         return -ENOMEM;
  354 
  355     r = crypt_cipher_init_kernel(&h->ck, name, mode, key, key_length);
  356     if (r < 0) {
  357         free(h);
  358         return r;
  359     }
  360 
  361     *ctx = h;
  362     return 0;
  363 }
  364 
  365 void crypt_cipher_destroy(struct crypt_cipher *ctx)
  366 {
  367     crypt_cipher_destroy_kernel(&ctx->ck);
  368     free(ctx);
  369 }
  370 
  371 int crypt_cipher_encrypt(struct crypt_cipher *ctx,
  372              const char *in, char *out, size_t length,
  373              const char *iv, size_t iv_length)
  374 {
  375     return crypt_cipher_encrypt_kernel(&ctx->ck, in, out, length, iv, iv_length);
  376 }
  377 
  378 int crypt_cipher_decrypt(struct crypt_cipher *ctx,
  379              const char *in, char *out, size_t length,
  380              const char *iv, size_t iv_length)
  381 {
  382     return crypt_cipher_decrypt_kernel(&ctx->ck, in, out, length, iv, iv_length);
  383 }
  384 
  385 bool crypt_cipher_kernel_only(struct crypt_cipher *ctx __attribute__((unused)))
  386 {
  387     return true;
  388 }
  389 
  390 int crypt_bitlk_decrypt_key(const void *key, size_t key_length,
  391                 const char *in, char *out, size_t length,
  392                 const char *iv, size_t iv_length,
  393                 const char *tag, size_t tag_length)
  394 {
  395     return crypt_bitlk_decrypt_key_kernel(key, key_length, in, out, length,
  396                           iv, iv_length, tag, tag_length);
  397 }