1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * Copyright (c) 2021 IBM Corporation 4 */ 5 6 #include <linux/module.h> 7 #include <crypto/internal/ecc.h> 8 #include <crypto/internal/sig.h> 9 #include <crypto/ecdh.h> 10 #include <crypto/sig.h> 11 #include <linux/asn1_decoder.h> 12 13 #include "ecdsasignature.asn1.h" 14 15 struct ecc_ctx { 16 unsigned int curve_id; 17 const struct ecc_curve *curve; 18 19 bool pub_key_set; 20 u64 x[ECC_MAX_DIGITS]; /* pub key x and y coordinates */ 21 u64 y[ECC_MAX_DIGITS]; 22 struct ecc_point pub_key; 23 }; 24 25 struct ecdsa_signature_ctx { 26 const struct ecc_curve *curve; 27 u64 r[ECC_MAX_DIGITS]; 28 u64 s[ECC_MAX_DIGITS]; 29 }; 30 31 /* 32 * Get the r and s components of a signature from the X509 certificate. 33 */ 34 static int ecdsa_get_signature_rs(u64 *dest, size_t hdrlen, unsigned char tag, 35 const void *value, size_t vlen, unsigned int ndigits) 36 { 37 size_t bufsize = ndigits * sizeof(u64); 38 ssize_t diff = vlen - bufsize; 39 const char *d = value; 40 41 if (!value || !vlen) 42 return -EINVAL; 43 44 /* diff = 0: 'value' has exacly the right size 45 * diff > 0: 'value' has too many bytes; one leading zero is allowed that 46 * makes the value a positive integer; error on more 47 * diff < 0: 'value' is missing leading zeros 48 */ 49 if (diff > 0) { 50 /* skip over leading zeros that make 'value' a positive int */ 51 if (*d == 0) { 52 vlen -= 1; 53 diff--; 54 d++; 55 } 56 if (diff) 57 return -EINVAL; 58 } 59 if (-diff >= bufsize) 60 return -EINVAL; 61 62 ecc_digits_from_bytes(d, vlen, dest, ndigits); 63 64 return 0; 65 } 66 67 int ecdsa_get_signature_r(void *context, size_t hdrlen, unsigned char tag, 68 const void *value, size_t vlen) 69 { 70 struct ecdsa_signature_ctx *sig = context; 71 72 return ecdsa_get_signature_rs(sig->r, hdrlen, tag, value, vlen, 73 sig->curve->g.ndigits); 74 } 75 76 int ecdsa_get_signature_s(void *context, size_t hdrlen, unsigned char tag, 77 const void *value, size_t vlen) 78 { 79 struct ecdsa_signature_ctx *sig = context; 80 81 return ecdsa_get_signature_rs(sig->s, hdrlen, tag, value, vlen, 82 sig->curve->g.ndigits); 83 } 84 85 static int _ecdsa_verify(struct ecc_ctx *ctx, const u64 *hash, const u64 *r, const u64 *s) 86 { 87 const struct ecc_curve *curve = ctx->curve; 88 unsigned int ndigits = curve->g.ndigits; 89 u64 s1[ECC_MAX_DIGITS]; 90 u64 u1[ECC_MAX_DIGITS]; 91 u64 u2[ECC_MAX_DIGITS]; 92 u64 x1[ECC_MAX_DIGITS]; 93 u64 y1[ECC_MAX_DIGITS]; 94 struct ecc_point res = ECC_POINT_INIT(x1, y1, ndigits); 95 96 /* 0 < r < n and 0 < s < n */ 97 if (vli_is_zero(r, ndigits) || vli_cmp(r, curve->n, ndigits) >= 0 || 98 vli_is_zero(s, ndigits) || vli_cmp(s, curve->n, ndigits) >= 0) 99 return -EBADMSG; 100 101 /* hash is given */ 102 pr_devel("hash : %016llx %016llx ... %016llx\n", 103 hash[ndigits - 1], hash[ndigits - 2], hash[0]); 104 105 /* s1 = (s^-1) mod n */ 106 vli_mod_inv(s1, s, curve->n, ndigits); 107 /* u1 = (hash * s1) mod n */ 108 vli_mod_mult_slow(u1, hash, s1, curve->n, ndigits); 109 /* u2 = (r * s1) mod n */ 110 vli_mod_mult_slow(u2, r, s1, curve->n, ndigits); 111 /* res = u1*G + u2 * pub_key */ 112 ecc_point_mult_shamir(&res, u1, &curve->g, u2, &ctx->pub_key, curve); 113 114 /* res.x = res.x mod n (if res.x > order) */ 115 if (unlikely(vli_cmp(res.x, curve->n, ndigits) == 1)) 116 /* faster alternative for NIST p521, p384, p256 & p192 */ 117 vli_sub(res.x, res.x, curve->n, ndigits); 118 119 if (!vli_cmp(res.x, r, ndigits)) 120 return 0; 121 122 return -EKEYREJECTED; 123 } 124 125 /* 126 * Verify an ECDSA signature. 127 */ 128 static int ecdsa_verify(struct crypto_sig *tfm, 129 const void *src, unsigned int slen, 130 const void *digest, unsigned int dlen) 131 { 132 struct ecc_ctx *ctx = crypto_sig_ctx(tfm); 133 size_t bufsize = ctx->curve->g.ndigits * sizeof(u64); 134 struct ecdsa_signature_ctx sig_ctx = { 135 .curve = ctx->curve, 136 }; 137 u64 hash[ECC_MAX_DIGITS]; 138 int ret; 139 140 if (unlikely(!ctx->pub_key_set)) 141 return -EINVAL; 142 143 ret = asn1_ber_decoder(&ecdsasignature_decoder, &sig_ctx, src, slen); 144 if (ret < 0) 145 return ret; 146 147 if (bufsize > dlen) 148 bufsize = dlen; 149 150 ecc_digits_from_bytes(digest, bufsize, hash, ctx->curve->g.ndigits); 151 152 return _ecdsa_verify(ctx, hash, sig_ctx.r, sig_ctx.s); 153 } 154 155 static int ecdsa_ecc_ctx_init(struct ecc_ctx *ctx, unsigned int curve_id) 156 { 157 ctx->curve_id = curve_id; 158 ctx->curve = ecc_get_curve(curve_id); 159 if (!ctx->curve) 160 return -EINVAL; 161 162 return 0; 163 } 164 165 166 static void ecdsa_ecc_ctx_deinit(struct ecc_ctx *ctx) 167 { 168 ctx->pub_key_set = false; 169 } 170 171 static int ecdsa_ecc_ctx_reset(struct ecc_ctx *ctx) 172 { 173 unsigned int curve_id = ctx->curve_id; 174 int ret; 175 176 ecdsa_ecc_ctx_deinit(ctx); 177 ret = ecdsa_ecc_ctx_init(ctx, curve_id); 178 if (ret == 0) 179 ctx->pub_key = ECC_POINT_INIT(ctx->x, ctx->y, 180 ctx->curve->g.ndigits); 181 return ret; 182 } 183 184 /* 185 * Set the public ECC key as defined by RFC5480 section 2.2 "Subject Public 186 * Key". Only the uncompressed format is supported. 187 */ 188 static int ecdsa_set_pub_key(struct crypto_sig *tfm, const void *key, 189 unsigned int keylen) 190 { 191 struct ecc_ctx *ctx = crypto_sig_ctx(tfm); 192 unsigned int digitlen, ndigits; 193 const unsigned char *d = key; 194 int ret; 195 196 ret = ecdsa_ecc_ctx_reset(ctx); 197 if (ret < 0) 198 return ret; 199 200 if (keylen < 1 || ((keylen - 1) & 1) != 0) 201 return -EINVAL; 202 /* we only accept uncompressed format indicated by '4' */ 203 if (d[0] != 4) 204 return -EINVAL; 205 206 keylen--; 207 digitlen = keylen >> 1; 208 209 ndigits = DIV_ROUND_UP(digitlen, sizeof(u64)); 210 if (ndigits != ctx->curve->g.ndigits) 211 return -EINVAL; 212 213 d++; 214 215 ecc_digits_from_bytes(d, digitlen, ctx->pub_key.x, ndigits); 216 ecc_digits_from_bytes(&d[digitlen], digitlen, ctx->pub_key.y, ndigits); 217 218 ret = ecc_is_pubkey_valid_full(ctx->curve, &ctx->pub_key); 219 220 ctx->pub_key_set = ret == 0; 221 222 return ret; 223 } 224 225 static void ecdsa_exit_tfm(struct crypto_sig *tfm) 226 { 227 struct ecc_ctx *ctx = crypto_sig_ctx(tfm); 228 229 ecdsa_ecc_ctx_deinit(ctx); 230 } 231 232 static unsigned int ecdsa_max_size(struct crypto_sig *tfm) 233 { 234 struct ecc_ctx *ctx = crypto_sig_ctx(tfm); 235 236 return DIV_ROUND_UP(ctx->curve->nbits, 8); 237 } 238 239 static int ecdsa_nist_p521_init_tfm(struct crypto_sig *tfm) 240 { 241 struct ecc_ctx *ctx = crypto_sig_ctx(tfm); 242 243 return ecdsa_ecc_ctx_init(ctx, ECC_CURVE_NIST_P521); 244 } 245 246 static struct sig_alg ecdsa_nist_p521 = { 247 .verify = ecdsa_verify, 248 .set_pub_key = ecdsa_set_pub_key, 249 .max_size = ecdsa_max_size, 250 .init = ecdsa_nist_p521_init_tfm, 251 .exit = ecdsa_exit_tfm, 252 .base = { 253 .cra_name = "ecdsa-nist-p521", 254 .cra_driver_name = "ecdsa-nist-p521-generic", 255 .cra_priority = 100, 256 .cra_module = THIS_MODULE, 257 .cra_ctxsize = sizeof(struct ecc_ctx), 258 }, 259 }; 260 261 static int ecdsa_nist_p384_init_tfm(struct crypto_sig *tfm) 262 { 263 struct ecc_ctx *ctx = crypto_sig_ctx(tfm); 264 265 return ecdsa_ecc_ctx_init(ctx, ECC_CURVE_NIST_P384); 266 } 267 268 static struct sig_alg ecdsa_nist_p384 = { 269 .verify = ecdsa_verify, 270 .set_pub_key = ecdsa_set_pub_key, 271 .max_size = ecdsa_max_size, 272 .init = ecdsa_nist_p384_init_tfm, 273 .exit = ecdsa_exit_tfm, 274 .base = { 275 .cra_name = "ecdsa-nist-p384", 276 .cra_driver_name = "ecdsa-nist-p384-generic", 277 .cra_priority = 100, 278 .cra_module = THIS_MODULE, 279 .cra_ctxsize = sizeof(struct ecc_ctx), 280 }, 281 }; 282 283 static int ecdsa_nist_p256_init_tfm(struct crypto_sig *tfm) 284 { 285 struct ecc_ctx *ctx = crypto_sig_ctx(tfm); 286 287 return ecdsa_ecc_ctx_init(ctx, ECC_CURVE_NIST_P256); 288 } 289 290 static struct sig_alg ecdsa_nist_p256 = { 291 .verify = ecdsa_verify, 292 .set_pub_key = ecdsa_set_pub_key, 293 .max_size = ecdsa_max_size, 294 .init = ecdsa_nist_p256_init_tfm, 295 .exit = ecdsa_exit_tfm, 296 .base = { 297 .cra_name = "ecdsa-nist-p256", 298 .cra_driver_name = "ecdsa-nist-p256-generic", 299 .cra_priority = 100, 300 .cra_module = THIS_MODULE, 301 .cra_ctxsize = sizeof(struct ecc_ctx), 302 }, 303 }; 304 305 static int ecdsa_nist_p192_init_tfm(struct crypto_sig *tfm) 306 { 307 struct ecc_ctx *ctx = crypto_sig_ctx(tfm); 308 309 return ecdsa_ecc_ctx_init(ctx, ECC_CURVE_NIST_P192); 310 } 311 312 static struct sig_alg ecdsa_nist_p192 = { 313 .verify = ecdsa_verify, 314 .set_pub_key = ecdsa_set_pub_key, 315 .max_size = ecdsa_max_size, 316 .init = ecdsa_nist_p192_init_tfm, 317 .exit = ecdsa_exit_tfm, 318 .base = { 319 .cra_name = "ecdsa-nist-p192", 320 .cra_driver_name = "ecdsa-nist-p192-generic", 321 .cra_priority = 100, 322 .cra_module = THIS_MODULE, 323 .cra_ctxsize = sizeof(struct ecc_ctx), 324 }, 325 }; 326 static bool ecdsa_nist_p192_registered; 327 328 static int __init ecdsa_init(void) 329 { 330 int ret; 331 332 /* NIST p192 may not be available in FIPS mode */ 333 ret = crypto_register_sig(&ecdsa_nist_p192); 334 ecdsa_nist_p192_registered = ret == 0; 335 336 ret = crypto_register_sig(&ecdsa_nist_p256); 337 if (ret) 338 goto nist_p256_error; 339 340 ret = crypto_register_sig(&ecdsa_nist_p384); 341 if (ret) 342 goto nist_p384_error; 343 344 ret = crypto_register_sig(&ecdsa_nist_p521); 345 if (ret) 346 goto nist_p521_error; 347 348 return 0; 349 350 nist_p521_error: 351 crypto_unregister_sig(&ecdsa_nist_p384); 352 353 nist_p384_error: 354 crypto_unregister_sig(&ecdsa_nist_p256); 355 356 nist_p256_error: 357 if (ecdsa_nist_p192_registered) 358 crypto_unregister_sig(&ecdsa_nist_p192); 359 return ret; 360 } 361 362 static void __exit ecdsa_exit(void) 363 { 364 if (ecdsa_nist_p192_registered) 365 crypto_unregister_sig(&ecdsa_nist_p192); 366 crypto_unregister_sig(&ecdsa_nist_p256); 367 crypto_unregister_sig(&ecdsa_nist_p384); 368 crypto_unregister_sig(&ecdsa_nist_p521); 369 } 370 371 subsys_initcall(ecdsa_init); 372 module_exit(ecdsa_exit); 373 374 MODULE_LICENSE("GPL"); 375 MODULE_AUTHOR("Stefan Berger <stefanb@linux.ibm.com>"); 376 MODULE_DESCRIPTION("ECDSA generic algorithm"); 377 MODULE_ALIAS_CRYPTO("ecdsa-nist-p192"); 378 MODULE_ALIAS_CRYPTO("ecdsa-nist-p256"); 379 MODULE_ALIAS_CRYPTO("ecdsa-nist-p384"); 380 MODULE_ALIAS_CRYPTO("ecdsa-nist-p521"); 381 MODULE_ALIAS_CRYPTO("ecdsa-generic"); 382