1 /* $OpenBSD: dsa_asn1.c,v 1.21 2018/02/20 17:48:35 tb 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/dsa.h> 65 #include <openssl/err.h> 66 67 /* Override the default new methods */ 68 static int 69 sig_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it, void *exarg) 70 { 71 if (operation == ASN1_OP_NEW_PRE) { 72 DSA_SIG *sig; 73 74 sig = malloc(sizeof(DSA_SIG)); 75 if (!sig) { 76 DSAerror(ERR_R_MALLOC_FAILURE); 77 return 0; 78 } 79 sig->r = NULL; 80 sig->s = NULL; 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 = &CBIGNUM_it, 102 }, 103 { 104 .flags = 0, 105 .tag = 0, 106 .offset = offsetof(DSA_SIG, s), 107 .field_name = "s", 108 .item = &CBIGNUM_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 130 int 131 i2d_DSA_SIG(const DSA_SIG *a, unsigned char **out) 132 { 133 return ASN1_item_i2d((ASN1_VALUE *)a, out, &DSA_SIG_it); 134 } 135 136 void 137 DSA_SIG_get0(const DSA_SIG *sig, const BIGNUM **pr, const BIGNUM **ps) 138 { 139 if (pr != NULL) 140 *pr = sig->r; 141 if (ps != NULL) 142 *ps = sig->s; 143 } 144 145 int 146 DSA_SIG_set0(DSA_SIG *sig, BIGNUM *r, BIGNUM *s) 147 { 148 if (r == NULL || s == NULL) 149 return 0; 150 151 BN_clear_free(sig->r); 152 sig->r = r; 153 BN_clear_free(sig->s); 154 sig->s = s; 155 156 return 1; 157 } 158 159 /* Override the default free and new methods */ 160 static int 161 dsa_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it, void *exarg) 162 { 163 if (operation == ASN1_OP_NEW_PRE) { 164 *pval = (ASN1_VALUE *)DSA_new(); 165 if (*pval) 166 return 2; 167 return 0; 168 } else if (operation == ASN1_OP_FREE_PRE) { 169 DSA_free((DSA *)*pval); 170 *pval = NULL; 171 return 2; 172 } 173 return 1; 174 } 175 176 static const ASN1_AUX DSAPrivateKey_aux = { 177 .app_data = NULL, 178 .flags = 0, 179 .ref_offset = 0, 180 .ref_lock = 0, 181 .asn1_cb = dsa_cb, 182 .enc_offset = 0, 183 }; 184 static const ASN1_TEMPLATE DSAPrivateKey_seq_tt[] = { 185 { 186 .flags = 0, 187 .tag = 0, 188 .offset = offsetof(DSA, version), 189 .field_name = "version", 190 .item = &LONG_it, 191 }, 192 { 193 .flags = 0, 194 .tag = 0, 195 .offset = offsetof(DSA, p), 196 .field_name = "p", 197 .item = &BIGNUM_it, 198 }, 199 { 200 .flags = 0, 201 .tag = 0, 202 .offset = offsetof(DSA, q), 203 .field_name = "q", 204 .item = &BIGNUM_it, 205 }, 206 { 207 .flags = 0, 208 .tag = 0, 209 .offset = offsetof(DSA, g), 210 .field_name = "g", 211 .item = &BIGNUM_it, 212 }, 213 { 214 .flags = 0, 215 .tag = 0, 216 .offset = offsetof(DSA, pub_key), 217 .field_name = "pub_key", 218 .item = &BIGNUM_it, 219 }, 220 { 221 .flags = 0, 222 .tag = 0, 223 .offset = offsetof(DSA, priv_key), 224 .field_name = "priv_key", 225 .item = &BIGNUM_it, 226 }, 227 }; 228 229 const ASN1_ITEM DSAPrivateKey_it = { 230 .itype = ASN1_ITYPE_SEQUENCE, 231 .utype = V_ASN1_SEQUENCE, 232 .templates = DSAPrivateKey_seq_tt, 233 .tcount = sizeof(DSAPrivateKey_seq_tt) / sizeof(ASN1_TEMPLATE), 234 .funcs = &DSAPrivateKey_aux, 235 .size = sizeof(DSA), 236 .sname = "DSA", 237 }; 238 239 240 DSA * 241 d2i_DSAPrivateKey(DSA **a, const unsigned char **in, long len) 242 { 243 return (DSA *)ASN1_item_d2i((ASN1_VALUE **)a, in, len, 244 &DSAPrivateKey_it); 245 } 246 247 int 248 i2d_DSAPrivateKey(const DSA *a, unsigned char **out) 249 { 250 return ASN1_item_i2d((ASN1_VALUE *)a, out, &DSAPrivateKey_it); 251 } 252 253 static const ASN1_AUX DSAparams_aux = { 254 .app_data = NULL, 255 .flags = 0, 256 .ref_offset = 0, 257 .ref_lock = 0, 258 .asn1_cb = dsa_cb, 259 .enc_offset = 0, 260 }; 261 static const ASN1_TEMPLATE DSAparams_seq_tt[] = { 262 { 263 .flags = 0, 264 .tag = 0, 265 .offset = offsetof(DSA, p), 266 .field_name = "p", 267 .item = &BIGNUM_it, 268 }, 269 { 270 .flags = 0, 271 .tag = 0, 272 .offset = offsetof(DSA, q), 273 .field_name = "q", 274 .item = &BIGNUM_it, 275 }, 276 { 277 .flags = 0, 278 .tag = 0, 279 .offset = offsetof(DSA, g), 280 .field_name = "g", 281 .item = &BIGNUM_it, 282 }, 283 }; 284 285 const ASN1_ITEM DSAparams_it = { 286 .itype = ASN1_ITYPE_SEQUENCE, 287 .utype = V_ASN1_SEQUENCE, 288 .templates = DSAparams_seq_tt, 289 .tcount = sizeof(DSAparams_seq_tt) / sizeof(ASN1_TEMPLATE), 290 .funcs = &DSAparams_aux, 291 .size = sizeof(DSA), 292 .sname = "DSA", 293 }; 294 295 296 DSA * 297 d2i_DSAparams(DSA **a, const unsigned char **in, long len) 298 { 299 return (DSA *)ASN1_item_d2i((ASN1_VALUE **)a, in, len, 300 &DSAparams_it); 301 } 302 303 int 304 i2d_DSAparams(const DSA *a, unsigned char **out) 305 { 306 return ASN1_item_i2d((ASN1_VALUE *)a, out, &DSAparams_it); 307 } 308 309 DSA * 310 d2i_DSAparams_bio(BIO *bp, DSA **a) 311 { 312 return ASN1_item_d2i_bio(&DSAparams_it, bp, a); 313 } 314 315 int 316 i2d_DSAparams_bio(BIO *bp, DSA *a) 317 { 318 return ASN1_item_i2d_bio(&DSAparams_it, bp, a); 319 } 320 321 DSA * 322 d2i_DSAparams_fp(FILE *fp, DSA **a) 323 { 324 return ASN1_item_d2i_fp(&DSAparams_it, fp, a); 325 } 326 327 int 328 i2d_DSAparams_fp(FILE *fp, DSA *a) 329 { 330 return ASN1_item_i2d_fp(&DSAparams_it, fp, a); 331 } 332 333 /* 334 * DSA public key is a bit trickier... its effectively a CHOICE type 335 * decided by a field called write_params which can either write out 336 * just the public key as an INTEGER or the parameters and public key 337 * in a SEQUENCE 338 */ 339 340 static const ASN1_TEMPLATE dsa_pub_internal_seq_tt[] = { 341 { 342 .flags = 0, 343 .tag = 0, 344 .offset = offsetof(DSA, pub_key), 345 .field_name = "pub_key", 346 .item = &BIGNUM_it, 347 }, 348 { 349 .flags = 0, 350 .tag = 0, 351 .offset = offsetof(DSA, p), 352 .field_name = "p", 353 .item = &BIGNUM_it, 354 }, 355 { 356 .flags = 0, 357 .tag = 0, 358 .offset = offsetof(DSA, q), 359 .field_name = "q", 360 .item = &BIGNUM_it, 361 }, 362 { 363 .flags = 0, 364 .tag = 0, 365 .offset = offsetof(DSA, g), 366 .field_name = "g", 367 .item = &BIGNUM_it, 368 }, 369 }; 370 371 const ASN1_ITEM dsa_pub_internal_it = { 372 .itype = ASN1_ITYPE_SEQUENCE, 373 .utype = V_ASN1_SEQUENCE, 374 .templates = dsa_pub_internal_seq_tt, 375 .tcount = sizeof(dsa_pub_internal_seq_tt) / sizeof(ASN1_TEMPLATE), 376 .funcs = NULL, 377 .size = sizeof(DSA), 378 .sname = "DSA", 379 }; 380 381 static const ASN1_AUX DSAPublicKey_aux = { 382 .app_data = NULL, 383 .flags = 0, 384 .ref_offset = 0, 385 .ref_lock = 0, 386 .asn1_cb = dsa_cb, 387 .enc_offset = 0, 388 }; 389 static const ASN1_TEMPLATE DSAPublicKey_ch_tt[] = { 390 { 391 .flags = 0, 392 .tag = 0, 393 .offset = offsetof(DSA, pub_key), 394 .field_name = "pub_key", 395 .item = &BIGNUM_it, 396 }, 397 { 398 .flags = 0 | ASN1_TFLG_COMBINE, 399 .tag = 0, 400 .offset = 0, 401 .field_name = NULL, 402 .item = &dsa_pub_internal_it, 403 }, 404 }; 405 406 const ASN1_ITEM DSAPublicKey_it = { 407 .itype = ASN1_ITYPE_CHOICE, 408 .utype = offsetof(DSA, write_params), 409 .templates = DSAPublicKey_ch_tt, 410 .tcount = sizeof(DSAPublicKey_ch_tt) / sizeof(ASN1_TEMPLATE), 411 .funcs = &DSAPublicKey_aux, 412 .size = sizeof(DSA), 413 .sname = "DSA", 414 }; 415 416 417 DSA * 418 d2i_DSAPublicKey(DSA **a, const unsigned char **in, long len) 419 { 420 return (DSA *)ASN1_item_d2i((ASN1_VALUE **)a, in, len, 421 &DSAPublicKey_it); 422 } 423 424 int 425 i2d_DSAPublicKey(const DSA *a, unsigned char **out) 426 { 427 return ASN1_item_i2d((ASN1_VALUE *)a, out, &DSAPublicKey_it); 428 } 429 430 DSA * 431 DSAparams_dup(DSA *dsa) 432 { 433 return ASN1_item_dup(&DSAparams_it, dsa); 434 } 435 436 int 437 DSA_sign(int type, const unsigned char *dgst, int dlen, unsigned char *sig, 438 unsigned int *siglen, DSA *dsa) 439 { 440 DSA_SIG *s; 441 442 s = DSA_do_sign(dgst, dlen, dsa); 443 if (s == NULL) { 444 *siglen = 0; 445 return 0; 446 } 447 *siglen = i2d_DSA_SIG(s,&sig); 448 DSA_SIG_free(s); 449 return 1; 450 } 451 452 /* 453 * data has already been hashed (probably with SHA or SHA-1). 454 * returns 455 * 1: correct signature 456 * 0: incorrect signature 457 * -1: error 458 */ 459 int 460 DSA_verify(int type, const unsigned char *dgst, int dgst_len, 461 const unsigned char *sigbuf, int siglen, DSA *dsa) 462 { 463 DSA_SIG *s; 464 unsigned char *der = NULL; 465 const unsigned char *p = sigbuf; 466 int derlen = -1; 467 int ret = -1; 468 469 s = DSA_SIG_new(); 470 if (s == NULL) 471 return ret; 472 if (d2i_DSA_SIG(&s, &p, siglen) == NULL) 473 goto err; 474 /* Ensure signature uses DER and doesn't have trailing garbage */ 475 derlen = i2d_DSA_SIG(s, &der); 476 if (derlen != siglen || memcmp(sigbuf, der, derlen)) 477 goto err; 478 ret = DSA_do_verify(dgst, dgst_len, s, dsa); 479 err: 480 freezero(der, derlen); 481 DSA_SIG_free(s); 482 return ret; 483 } 484