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