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