1 /* $OpenBSD: dsa_asn1.c,v 1.31 2023/07/08 14:28:15 beck Exp $ */ 2 /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL 3 * project 2000. 4 */ 5 /* ==================================================================== 6 * Copyright (c) 2000-2005 The OpenSSL Project. All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in 17 * the documentation and/or other materials provided with the 18 * distribution. 19 * 20 * 3. All advertising materials mentioning features or use of this 21 * software must display the following acknowledgment: 22 * "This product includes software developed by the OpenSSL Project 23 * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" 24 * 25 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 26 * endorse or promote products derived from this software without 27 * prior written permission. For written permission, please contact 28 * licensing@OpenSSL.org. 29 * 30 * 5. Products derived from this software may not be called "OpenSSL" 31 * nor may "OpenSSL" appear in their names without prior written 32 * permission of the OpenSSL Project. 33 * 34 * 6. Redistributions of any form whatsoever must retain the following 35 * acknowledgment: 36 * "This product includes software developed by the OpenSSL Project 37 * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" 38 * 39 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 40 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 41 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 42 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 43 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 44 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 45 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 46 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 47 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 48 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 49 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 50 * OF THE POSSIBILITY OF SUCH DAMAGE. 51 * ==================================================================== 52 * 53 * This product includes cryptographic software written by Eric Young 54 * (eay@cryptsoft.com). This product includes software written by Tim 55 * Hudson (tjh@cryptsoft.com). 56 * 57 */ 58 59 #include <stdio.h> 60 #include <string.h> 61 62 #include <openssl/asn1.h> 63 #include <openssl/asn1t.h> 64 #include <openssl/bn.h> 65 #include <openssl/dsa.h> 66 #include <openssl/err.h> 67 68 #include "dsa_local.h" 69 70 /* Override the default new methods */ 71 static int 72 sig_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it, void *exarg) 73 { 74 if (operation == ASN1_OP_NEW_PRE) { 75 DSA_SIG *sig; 76 77 if ((sig = DSA_SIG_new()) == NULL) { 78 DSAerror(ERR_R_MALLOC_FAILURE); 79 return 0; 80 } 81 *pval = (ASN1_VALUE *)sig; 82 return 2; 83 } 84 return 1; 85 } 86 87 static const ASN1_AUX DSA_SIG_aux = { 88 .app_data = NULL, 89 .flags = 0, 90 .ref_offset = 0, 91 .ref_lock = 0, 92 .asn1_cb = sig_cb, 93 .enc_offset = 0, 94 }; 95 static const ASN1_TEMPLATE DSA_SIG_seq_tt[] = { 96 { 97 .flags = 0, 98 .tag = 0, 99 .offset = offsetof(DSA_SIG, r), 100 .field_name = "r", 101 .item = &BIGNUM_it, 102 }, 103 { 104 .flags = 0, 105 .tag = 0, 106 .offset = offsetof(DSA_SIG, s), 107 .field_name = "s", 108 .item = &BIGNUM_it, 109 }, 110 }; 111 112 const ASN1_ITEM DSA_SIG_it = { 113 .itype = ASN1_ITYPE_SEQUENCE, 114 .utype = V_ASN1_SEQUENCE, 115 .templates = DSA_SIG_seq_tt, 116 .tcount = sizeof(DSA_SIG_seq_tt) / sizeof(ASN1_TEMPLATE), 117 .funcs = &DSA_SIG_aux, 118 .size = sizeof(DSA_SIG), 119 .sname = "DSA_SIG", 120 }; 121 122 123 DSA_SIG * 124 d2i_DSA_SIG(DSA_SIG **a, const unsigned char **in, long len) 125 { 126 return (DSA_SIG *)ASN1_item_d2i((ASN1_VALUE **)a, in, len, 127 &DSA_SIG_it); 128 } 129 LCRYPTO_ALIAS(d2i_DSA_SIG); 130 131 int 132 i2d_DSA_SIG(const DSA_SIG *a, unsigned char **out) 133 { 134 return ASN1_item_i2d((ASN1_VALUE *)a, out, &DSA_SIG_it); 135 } 136 LCRYPTO_ALIAS(i2d_DSA_SIG); 137 138 void 139 DSA_SIG_get0(const DSA_SIG *sig, const BIGNUM **pr, const BIGNUM **ps) 140 { 141 if (pr != NULL) 142 *pr = sig->r; 143 if (ps != NULL) 144 *ps = sig->s; 145 } 146 LCRYPTO_ALIAS(DSA_SIG_get0); 147 148 int 149 DSA_SIG_set0(DSA_SIG *sig, BIGNUM *r, BIGNUM *s) 150 { 151 if (r == NULL || s == NULL) 152 return 0; 153 154 BN_free(sig->r); 155 sig->r = r; 156 BN_free(sig->s); 157 sig->s = s; 158 159 return 1; 160 } 161 LCRYPTO_ALIAS(DSA_SIG_set0); 162 163 /* Override the default free and new methods */ 164 static int 165 dsa_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it, void *exarg) 166 { 167 if (operation == ASN1_OP_NEW_PRE) { 168 *pval = (ASN1_VALUE *)DSA_new(); 169 if (*pval) 170 return 2; 171 return 0; 172 } else if (operation == ASN1_OP_FREE_PRE) { 173 DSA_free((DSA *)*pval); 174 *pval = NULL; 175 return 2; 176 } 177 return 1; 178 } 179 180 static const ASN1_AUX DSAPrivateKey_aux = { 181 .app_data = NULL, 182 .flags = 0, 183 .ref_offset = 0, 184 .ref_lock = 0, 185 .asn1_cb = dsa_cb, 186 .enc_offset = 0, 187 }; 188 static const ASN1_TEMPLATE DSAPrivateKey_seq_tt[] = { 189 { 190 .flags = 0, 191 .tag = 0, 192 .offset = offsetof(DSA, version), 193 .field_name = "version", 194 .item = &LONG_it, 195 }, 196 { 197 .flags = 0, 198 .tag = 0, 199 .offset = offsetof(DSA, p), 200 .field_name = "p", 201 .item = &BIGNUM_it, 202 }, 203 { 204 .flags = 0, 205 .tag = 0, 206 .offset = offsetof(DSA, q), 207 .field_name = "q", 208 .item = &BIGNUM_it, 209 }, 210 { 211 .flags = 0, 212 .tag = 0, 213 .offset = offsetof(DSA, g), 214 .field_name = "g", 215 .item = &BIGNUM_it, 216 }, 217 { 218 .flags = 0, 219 .tag = 0, 220 .offset = offsetof(DSA, pub_key), 221 .field_name = "pub_key", 222 .item = &BIGNUM_it, 223 }, 224 { 225 .flags = 0, 226 .tag = 0, 227 .offset = offsetof(DSA, priv_key), 228 .field_name = "priv_key", 229 .item = &BIGNUM_it, 230 }, 231 }; 232 233 const ASN1_ITEM DSAPrivateKey_it = { 234 .itype = ASN1_ITYPE_SEQUENCE, 235 .utype = V_ASN1_SEQUENCE, 236 .templates = DSAPrivateKey_seq_tt, 237 .tcount = sizeof(DSAPrivateKey_seq_tt) / sizeof(ASN1_TEMPLATE), 238 .funcs = &DSAPrivateKey_aux, 239 .size = sizeof(DSA), 240 .sname = "DSA", 241 }; 242 243 244 DSA * 245 d2i_DSAPrivateKey(DSA **a, const unsigned char **in, long len) 246 { 247 return (DSA *)ASN1_item_d2i((ASN1_VALUE **)a, in, len, 248 &DSAPrivateKey_it); 249 } 250 LCRYPTO_ALIAS(d2i_DSAPrivateKey); 251 252 int 253 i2d_DSAPrivateKey(const DSA *a, unsigned char **out) 254 { 255 return ASN1_item_i2d((ASN1_VALUE *)a, out, &DSAPrivateKey_it); 256 } 257 LCRYPTO_ALIAS(i2d_DSAPrivateKey); 258 259 static const ASN1_AUX DSAparams_aux = { 260 .app_data = NULL, 261 .flags = 0, 262 .ref_offset = 0, 263 .ref_lock = 0, 264 .asn1_cb = dsa_cb, 265 .enc_offset = 0, 266 }; 267 static const ASN1_TEMPLATE DSAparams_seq_tt[] = { 268 { 269 .flags = 0, 270 .tag = 0, 271 .offset = offsetof(DSA, p), 272 .field_name = "p", 273 .item = &BIGNUM_it, 274 }, 275 { 276 .flags = 0, 277 .tag = 0, 278 .offset = offsetof(DSA, q), 279 .field_name = "q", 280 .item = &BIGNUM_it, 281 }, 282 { 283 .flags = 0, 284 .tag = 0, 285 .offset = offsetof(DSA, g), 286 .field_name = "g", 287 .item = &BIGNUM_it, 288 }, 289 }; 290 291 const ASN1_ITEM DSAparams_it = { 292 .itype = ASN1_ITYPE_SEQUENCE, 293 .utype = V_ASN1_SEQUENCE, 294 .templates = DSAparams_seq_tt, 295 .tcount = sizeof(DSAparams_seq_tt) / sizeof(ASN1_TEMPLATE), 296 .funcs = &DSAparams_aux, 297 .size = sizeof(DSA), 298 .sname = "DSA", 299 }; 300 301 302 DSA * 303 d2i_DSAparams(DSA **a, const unsigned char **in, long len) 304 { 305 return (DSA *)ASN1_item_d2i((ASN1_VALUE **)a, in, len, 306 &DSAparams_it); 307 } 308 LCRYPTO_ALIAS(d2i_DSAparams); 309 310 int 311 i2d_DSAparams(const DSA *a, unsigned char **out) 312 { 313 return ASN1_item_i2d((ASN1_VALUE *)a, out, &DSAparams_it); 314 } 315 LCRYPTO_ALIAS(i2d_DSAparams); 316 317 DSA * 318 d2i_DSAparams_bio(BIO *bp, DSA **a) 319 { 320 return ASN1_item_d2i_bio(&DSAparams_it, bp, a); 321 } 322 LCRYPTO_ALIAS(d2i_DSAparams_bio); 323 324 int 325 i2d_DSAparams_bio(BIO *bp, DSA *a) 326 { 327 return ASN1_item_i2d_bio(&DSAparams_it, bp, a); 328 } 329 LCRYPTO_ALIAS(i2d_DSAparams_bio); 330 331 DSA * 332 d2i_DSAparams_fp(FILE *fp, DSA **a) 333 { 334 return ASN1_item_d2i_fp(&DSAparams_it, fp, a); 335 } 336 LCRYPTO_ALIAS(d2i_DSAparams_fp); 337 338 int 339 i2d_DSAparams_fp(FILE *fp, DSA *a) 340 { 341 return ASN1_item_i2d_fp(&DSAparams_it, fp, a); 342 } 343 LCRYPTO_ALIAS(i2d_DSAparams_fp); 344 345 static const ASN1_AUX DSAPublicKey_aux = { 346 .app_data = NULL, 347 .flags = 0, 348 .ref_offset = 0, 349 .ref_lock = 0, 350 .asn1_cb = dsa_cb, 351 .enc_offset = 0, 352 }; 353 static const ASN1_TEMPLATE DSAPublicKey_seq_tt[] = { 354 { 355 .flags = 0, 356 .tag = 0, 357 .offset = offsetof(DSA, pub_key), 358 .field_name = "pub_key", 359 .item = &BIGNUM_it, 360 }, 361 { 362 .flags = 0, 363 .tag = 0, 364 .offset = offsetof(DSA, p), 365 .field_name = "p", 366 .item = &BIGNUM_it, 367 }, 368 { 369 .flags = 0, 370 .tag = 0, 371 .offset = offsetof(DSA, q), 372 .field_name = "q", 373 .item = &BIGNUM_it, 374 }, 375 { 376 .flags = 0, 377 .tag = 0, 378 .offset = offsetof(DSA, g), 379 .field_name = "g", 380 .item = &BIGNUM_it, 381 }, 382 }; 383 384 const ASN1_ITEM DSAPublicKey_it = { 385 .itype = ASN1_ITYPE_SEQUENCE, 386 .utype = V_ASN1_SEQUENCE, 387 .templates = DSAPublicKey_seq_tt, 388 .tcount = sizeof(DSAPublicKey_seq_tt) / sizeof(ASN1_TEMPLATE), 389 .funcs = &DSAPublicKey_aux, 390 .size = sizeof(DSA), 391 .sname = "DSA", 392 }; 393 394 DSA * 395 d2i_DSAPublicKey(DSA **a, const unsigned char **in, long len) 396 { 397 return (DSA *)ASN1_item_d2i((ASN1_VALUE **)a, in, len, 398 &DSAPublicKey_it); 399 } 400 LCRYPTO_ALIAS(d2i_DSAPublicKey); 401 402 int 403 i2d_DSAPublicKey(const DSA *a, unsigned char **out) 404 { 405 return ASN1_item_i2d((ASN1_VALUE *)a, out, &DSAPublicKey_it); 406 } 407 LCRYPTO_ALIAS(i2d_DSAPublicKey); 408 409 DSA * 410 DSAparams_dup(DSA *dsa) 411 { 412 return ASN1_item_dup(&DSAparams_it, dsa); 413 } 414 LCRYPTO_ALIAS(DSAparams_dup); 415 416 int 417 DSA_sign(int type, const unsigned char *dgst, int dlen, unsigned char *sig, 418 unsigned int *out_siglen, DSA *dsa) 419 { 420 DSA_SIG *s; 421 int siglen; 422 int ret = 0; 423 424 *out_siglen = 0; 425 426 if ((s = DSA_do_sign(dgst, dlen, dsa)) == NULL) 427 goto err; 428 429 if ((siglen = i2d_DSA_SIG(s, &sig)) < 0) 430 goto err; 431 432 *out_siglen = siglen; 433 434 ret = 1; 435 err: 436 DSA_SIG_free(s); 437 438 return ret; 439 } 440 LCRYPTO_ALIAS(DSA_sign); 441 442 /* 443 * data has already been hashed (probably with SHA or SHA-1). 444 * returns 445 * 1: correct signature 446 * 0: incorrect signature 447 * -1: error 448 */ 449 int 450 DSA_verify(int type, const unsigned char *dgst, int dgst_len, 451 const unsigned char *sigbuf, int siglen, DSA *dsa) 452 { 453 DSA_SIG *s = NULL; 454 unsigned char *der = NULL; 455 const unsigned char *p; 456 int ret = -1; 457 458 p = sigbuf; 459 if ((s = d2i_DSA_SIG(NULL, &p, siglen)) == NULL) 460 goto err; 461 462 /* Ensure signature uses DER and doesn't have trailing garbage */ 463 if (i2d_DSA_SIG(s, &der) != siglen) 464 goto err; 465 466 if (memcmp(der, sigbuf, siglen) != 0) 467 goto err; 468 469 ret = DSA_do_verify(dgst, dgst_len, s, dsa); 470 err: 471 free(der); 472 DSA_SIG_free(s); 473 474 return ret; 475 } 476 LCRYPTO_ALIAS(DSA_verify); 477