1/* 2 * Scatterlist Cryptographic API. 3 * 4 * Copyright (c) 2002 James Morris <jmorris@intercode.com.au> 5 * Copyright (c) 2002 David S. Miller (davem@redhat.com) 6 * 7 * Portions derived from Cryptoapi, by Alexander Kjeldaas <astor@fast.no> 8 * and Nettle, by Niels M���ler. 9 * 10 * This program is free software; you can redistribute it and/or modify it 11 * under the terms of the GNU General Public License as published by the Free 12 * Software Foundation; either version 2 of the License, or (at your option) 13 * any later version. 14 * 15 */ 16#include "kmap_types.h" 17 18#include <linux/init.h> 19#include <linux/module.h> 20//#include <linux/crypto.h> 21#include "rtl_crypto.h" 22#include <linux/errno.h> 23#include <linux/rwsem.h> 24#include <linux/slab.h> 25#include "internal.h" 26 27LIST_HEAD(crypto_alg_list); 28DECLARE_RWSEM(crypto_alg_sem); 29 30static inline int crypto_alg_get(struct crypto_alg *alg) 31{ 32 return try_inc_mod_count(alg->cra_module); 33} 34 35static inline void crypto_alg_put(struct crypto_alg *alg) 36{ 37 if (alg->cra_module) 38 __MOD_DEC_USE_COUNT(alg->cra_module); 39} 40 41struct crypto_alg *crypto_alg_lookup(const char *name) 42{ 43 struct crypto_alg *q, *alg = NULL; 44 45 if (!name) 46 return NULL; 47 48 down_read(&crypto_alg_sem); 49 50 list_for_each_entry(q, &crypto_alg_list, cra_list) { 51 if (!(strcmp(q->cra_name, name))) { 52 if (crypto_alg_get(q)) 53 alg = q; 54 break; 55 } 56 } 57 58 up_read(&crypto_alg_sem); 59 return alg; 60} 61 62static int crypto_init_flags(struct crypto_tfm *tfm, u32 flags) 63{ 64 tfm->crt_flags = 0; 65 66 switch (crypto_tfm_alg_type(tfm)) { 67 case CRYPTO_ALG_TYPE_CIPHER: 68 return crypto_init_cipher_flags(tfm, flags); 69 70 case CRYPTO_ALG_TYPE_DIGEST: 71 return crypto_init_digest_flags(tfm, flags); 72 73 case CRYPTO_ALG_TYPE_COMPRESS: 74 return crypto_init_compress_flags(tfm, flags); 75 76 default: 77 break; 78 } 79 80 BUG(); 81 return -EINVAL; 82} 83 84static int crypto_init_ops(struct crypto_tfm *tfm) 85{ 86 switch (crypto_tfm_alg_type(tfm)) { 87 case CRYPTO_ALG_TYPE_CIPHER: 88 return crypto_init_cipher_ops(tfm); 89 90 case CRYPTO_ALG_TYPE_DIGEST: 91 return crypto_init_digest_ops(tfm); 92 93 case CRYPTO_ALG_TYPE_COMPRESS: 94 return crypto_init_compress_ops(tfm); 95 96 default: 97 break; 98 } 99 100 BUG(); 101 return -EINVAL; 102} 103 104static void crypto_exit_ops(struct crypto_tfm *tfm) 105{ 106 switch (crypto_tfm_alg_type(tfm)) { 107 case CRYPTO_ALG_TYPE_CIPHER: 108 crypto_exit_cipher_ops(tfm); 109 break; 110 111 case CRYPTO_ALG_TYPE_DIGEST: 112 crypto_exit_digest_ops(tfm); 113 break; 114 115 case CRYPTO_ALG_TYPE_COMPRESS: 116 crypto_exit_compress_ops(tfm); 117 break; 118 119 default: 120 BUG(); 121 122 } 123} 124 125struct crypto_tfm *crypto_alloc_tfm(const char *name, u32 flags) 126{ 127 struct crypto_tfm *tfm = NULL; 128 struct crypto_alg *alg; 129 130 alg = crypto_alg_mod_lookup(name); 131 if (alg == NULL) 132 goto out; 133 134 tfm = kzalloc(sizeof(*tfm) + alg->cra_ctxsize, GFP_KERNEL); 135 if (tfm == NULL) 136 goto out_put; 137 138 tfm->__crt_alg = alg; 139 140 if (crypto_init_flags(tfm, flags)) 141 goto out_free_tfm; 142 143 if (crypto_init_ops(tfm)) { 144 crypto_exit_ops(tfm); 145 goto out_free_tfm; 146 } 147 148 goto out; 149 150out_free_tfm: 151 kfree(tfm); 152 tfm = NULL; 153out_put: 154 crypto_alg_put(alg); 155out: 156 return tfm; 157} 158 159void crypto_free_tfm(struct crypto_tfm *tfm) 160{ 161 struct crypto_alg *alg = tfm->__crt_alg; 162 int size = sizeof(*tfm) + alg->cra_ctxsize; 163 164 crypto_exit_ops(tfm); 165 crypto_alg_put(alg); 166 memset(tfm, 0, size); 167 kfree(tfm); 168} 169 170int crypto_register_alg(struct crypto_alg *alg) 171{ 172 int ret = 0; 173 struct crypto_alg *q; 174 175 down_write(&crypto_alg_sem); 176 177 list_for_each_entry(q, &crypto_alg_list, cra_list) { 178 if (!(strcmp(q->cra_name, alg->cra_name))) { 179 ret = -EEXIST; 180 goto out; 181 } 182 } 183 184 list_add_tail(&alg->cra_list, &crypto_alg_list); 185out: 186 up_write(&crypto_alg_sem); 187 return ret; 188} 189 190int crypto_unregister_alg(struct crypto_alg *alg) 191{ 192 int ret = -ENOENT; 193 struct crypto_alg *q; 194 195 BUG_ON(!alg->cra_module); 196 197 down_write(&crypto_alg_sem); 198 list_for_each_entry(q, &crypto_alg_list, cra_list) { 199 if (alg == q) { 200 list_del(&alg->cra_list); 201 ret = 0; 202 goto out; 203 } 204 } 205out: 206 up_write(&crypto_alg_sem); 207 return ret; 208} 209 210int crypto_alg_available(const char *name, u32 flags) 211{ 212 int ret = 0; 213 struct crypto_alg *alg = crypto_alg_mod_lookup(name); 214 215 if (alg) { 216 crypto_alg_put(alg); 217 ret = 1; 218 } 219 220 return ret; 221} 222 223static int __init init_crypto(void) 224{ 225 printk(KERN_INFO "Initializing Cryptographic API\n"); 226 crypto_init_proc(); 227 return 0; 228} 229 230__initcall(init_crypto); 231 232/* 233EXPORT_SYMBOL_GPL(crypto_register_alg); 234EXPORT_SYMBOL_GPL(crypto_unregister_alg); 235EXPORT_SYMBOL_GPL(crypto_alloc_tfm); 236EXPORT_SYMBOL_GPL(crypto_free_tfm); 237EXPORT_SYMBOL_GPL(crypto_alg_available); 238*/ 239 240EXPORT_SYMBOL_NOVERS(crypto_register_alg); 241EXPORT_SYMBOL_NOVERS(crypto_unregister_alg); 242EXPORT_SYMBOL_NOVERS(crypto_alloc_tfm); 243EXPORT_SYMBOL_NOVERS(crypto_free_tfm); 244EXPORT_SYMBOL_NOVERS(crypto_alg_available); 245