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