Annotation of embedaddon/strongswan/src/libstrongswan/plugins/bliss/bliss_public_key.c, revision 1.1
1.1 ! misho 1: /*
! 2: * Copyright (C) 2014-2016 Andreas Steffen
! 3: * HSR Hochschule fuer Technik Rapperswil
! 4: *
! 5: * This program is free software; you can redistribute it and/or modify it
! 6: * under the terms of the GNU General Public License as published by the
! 7: * Free Software Foundation; either version 2 of the License, or (at your
! 8: * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
! 9: *
! 10: * This program is distributed in the hope that it will be useful, but
! 11: * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
! 12: * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
! 13: * for more details.
! 14: */
! 15:
! 16: #include "bliss_public_key.h"
! 17: #include "bliss_signature.h"
! 18: #include "bliss_bitpacker.h"
! 19: #include "ntt_fft.h"
! 20: #include "ntt_fft_reduce.h"
! 21: #include "bliss_utils.h"
! 22:
! 23: #include <asn1/asn1.h>
! 24: #include <asn1/asn1_parser.h>
! 25: #include <asn1/oid.h>
! 26:
! 27: typedef struct private_bliss_public_key_t private_bliss_public_key_t;
! 28:
! 29: /**
! 30: * Private data structure with signing context.
! 31: */
! 32: struct private_bliss_public_key_t {
! 33: /**
! 34: * Public interface for this signer.
! 35: */
! 36: bliss_public_key_t public;
! 37:
! 38: /**
! 39: * BLISS signature parameter set
! 40: */
! 41: const bliss_param_set_t *set;
! 42:
! 43: /**
! 44: * NTT of BLISS public key a (coefficients of polynomial (2g + 1)/f)
! 45: */
! 46: uint32_t *A;
! 47:
! 48: /**
! 49: * NTT of BLISS public key in Montgomery representation Ar = rA mod
! 50: */
! 51: uint32_t *Ar;
! 52:
! 53: /**
! 54: * reference counter
! 55: */
! 56: refcount_t ref;
! 57: };
! 58:
! 59: METHOD(public_key_t, get_type, key_type_t,
! 60: private_bliss_public_key_t *this)
! 61: {
! 62: return KEY_BLISS;
! 63: }
! 64:
! 65: /**
! 66: * Verify a BLISS signature based on a SHA-512 hash
! 67: */
! 68: static bool verify_bliss(private_bliss_public_key_t *this, hash_algorithm_t alg,
! 69: chunk_t data, chunk_t signature)
! 70: {
! 71: int i, n;
! 72: int32_t *z1, *u;
! 73: int16_t *ud, *z2d;
! 74: uint16_t q, q2, p, *c_indices, *indices;
! 75: uint32_t *az;
! 76: uint8_t data_hash_buf[HASH_SIZE_SHA512];
! 77: chunk_t data_hash;
! 78: hasher_t *hasher;
! 79: ext_out_function_t oracle_alg;
! 80: ntt_fft_t *fft;
! 81: bliss_signature_t *sig;
! 82: bool success = FALSE;
! 83:
! 84: /* Create data hash using configurable hash algorithm */
! 85: hasher = lib->crypto->create_hasher(lib->crypto, alg);
! 86: if (!hasher )
! 87: {
! 88: return FALSE;
! 89: }
! 90: data_hash = chunk_create(data_hash_buf, hasher->get_hash_size(hasher));
! 91:
! 92: if (!hasher->get_hash(hasher, data, data_hash_buf))
! 93: {
! 94: hasher->destroy(hasher);
! 95: return FALSE;
! 96: }
! 97: hasher->destroy(hasher);
! 98:
! 99: sig = bliss_signature_create_from_data(this->set, signature);
! 100: if (!sig)
! 101: {
! 102: return FALSE;
! 103: }
! 104: sig->get_parameters(sig, &z1, &z2d, &c_indices);
! 105:
! 106: if (!bliss_utils_check_norms(this->set, z1, z2d))
! 107: {
! 108: sig->destroy(sig);
! 109: return FALSE;
! 110: }
! 111:
! 112: /* MGF1 hash algorithm to be used for random oracle */
! 113: oracle_alg = XOF_MGF1_SHA512;
! 114:
! 115: /* Initialize a couple of needed variables */
! 116: n = this->set->n;
! 117: q = this->set->q;
! 118: p = this->set->p;
! 119: q2 = 2 * q;
! 120: az = malloc(n * sizeof(uint32_t));
! 121: u = malloc(n * sizeof(int32_t));
! 122: ud = malloc(n * sizeof(int16_t));
! 123: indices = malloc(this->set->kappa * sizeof(uint16_t));
! 124:
! 125: for (i = 0; i < n; i++)
! 126: {
! 127: az[i] = z1[i] < 0 ? q + z1[i] : z1[i];
! 128: }
! 129: fft = ntt_fft_create(this->set->fft_params);
! 130: fft->transform(fft, az, az, FALSE);
! 131:
! 132: for (i = 0; i < n; i++)
! 133: {
! 134: az[i] = ntt_fft_mreduce(this->Ar[i] * az[i], this->set->fft_params);
! 135: }
! 136: fft->transform(fft, az, az, TRUE);
! 137:
! 138: for (i = 0; i < n; i++)
! 139: {
! 140: u[i] = (2 * this->set->q2_inv * az[i]) % q2;
! 141: }
! 142:
! 143: for (i = 0; i < this->set->kappa; i++)
! 144: {
! 145: u[c_indices[i]] = (u[c_indices[i]] + q * this->set->q2_inv) % q2;
! 146: }
! 147: bliss_utils_round_and_drop(this->set, u, ud);
! 148:
! 149: for (i = 0; i < n; i++)
! 150: {
! 151: ud[i] += z2d[i];
! 152: if (ud[i] < 0)
! 153: {
! 154: ud[i] += p;
! 155: }
! 156: else if (ud[i] >= p)
! 157: {
! 158: ud[i] -= p;
! 159: }
! 160: }
! 161:
! 162: /* Detailed debugging information */
! 163: DBG3(DBG_LIB, " i u[i] ud[i] z2d[i]");
! 164: for (i = 0; i < n; i++)
! 165: {
! 166: DBG3(DBG_LIB, "%3d %6d %4d %4d", i, u[i], ud[i], z2d[i]);
! 167: }
! 168:
! 169: if (!bliss_utils_generate_c(oracle_alg, data_hash, ud, this->set, indices))
! 170: {
! 171: goto end;
! 172: }
! 173:
! 174: for (i = 0; i < this->set->kappa; i++)
! 175: {
! 176: if (indices[i] != c_indices[i])
! 177: {
! 178: DBG1(DBG_LIB, "signature verification failed");
! 179: goto end;
! 180: }
! 181: }
! 182: success = TRUE;
! 183:
! 184: end:
! 185: /* cleanup */
! 186: sig->destroy(sig);
! 187: fft->destroy(fft);
! 188: free(az);
! 189: free(u);
! 190: free(ud);
! 191: free(indices);
! 192:
! 193: return success;
! 194: }
! 195:
! 196: METHOD(public_key_t, verify, bool,
! 197: private_bliss_public_key_t *this, signature_scheme_t scheme, void *params,
! 198: chunk_t data, chunk_t signature)
! 199: {
! 200: switch (scheme)
! 201: {
! 202: case SIGN_BLISS_WITH_SHA2_256:
! 203: return verify_bliss(this, HASH_SHA256, data, signature);
! 204: case SIGN_BLISS_WITH_SHA2_384:
! 205: return verify_bliss(this, HASH_SHA384, data, signature);
! 206: case SIGN_BLISS_WITH_SHA2_512:
! 207: return verify_bliss(this, HASH_SHA512, data, signature);
! 208: case SIGN_BLISS_WITH_SHA3_256:
! 209: return verify_bliss(this, HASH_SHA3_256, data, signature);
! 210: case SIGN_BLISS_WITH_SHA3_384:
! 211: return verify_bliss(this, HASH_SHA3_384, data, signature);
! 212: case SIGN_BLISS_WITH_SHA3_512:
! 213: return verify_bliss(this, HASH_SHA3_512, data, signature);
! 214: default:
! 215: DBG1(DBG_LIB, "signature scheme %N not supported by BLISS",
! 216: signature_scheme_names, scheme);
! 217: return FALSE;
! 218: }
! 219: }
! 220:
! 221: METHOD(public_key_t, encrypt_, bool,
! 222: private_bliss_public_key_t *this, encryption_scheme_t scheme,
! 223: chunk_t plain, chunk_t *crypto)
! 224: {
! 225: DBG1(DBG_LIB, "encryption scheme %N not supported",
! 226: encryption_scheme_names, scheme);
! 227: return FALSE;
! 228: }
! 229:
! 230: METHOD(public_key_t, get_keysize, int,
! 231: private_bliss_public_key_t *this)
! 232: {
! 233: return this->set->strength;
! 234: }
! 235:
! 236: METHOD(public_key_t, get_encoding, bool,
! 237: private_bliss_public_key_t *this, cred_encoding_type_t type,
! 238: chunk_t *encoding)
! 239: {
! 240: bool success = TRUE;
! 241:
! 242: *encoding = bliss_public_key_info_encode(this->set->oid, this->A, this->set);
! 243:
! 244: if (type != PUBKEY_SPKI_ASN1_DER)
! 245: {
! 246: chunk_t asn1_encoding = *encoding;
! 247:
! 248: success = lib->encoding->encode(lib->encoding, type,
! 249: NULL, encoding, CRED_PART_BLISS_PUB_ASN1_DER,
! 250: asn1_encoding, CRED_PART_END);
! 251: chunk_clear(&asn1_encoding);
! 252: }
! 253: return success;
! 254: }
! 255:
! 256: METHOD(public_key_t, get_fingerprint, bool,
! 257: private_bliss_public_key_t *this, cred_encoding_type_t type, chunk_t *fp)
! 258: {
! 259: bool success;
! 260:
! 261: if (lib->encoding->get_cache(lib->encoding, type, this, fp))
! 262: {
! 263: return TRUE;
! 264: }
! 265: success = bliss_public_key_fingerprint(this->set->oid, this->A,
! 266: this->set, type, fp);
! 267: if (success)
! 268: {
! 269: lib->encoding->cache(lib->encoding, type, this, *fp);
! 270: }
! 271: return success;
! 272: }
! 273:
! 274: METHOD(public_key_t, get_ref, public_key_t*,
! 275: private_bliss_public_key_t *this)
! 276: {
! 277: ref_get(&this->ref);
! 278: return &this->public.key;
! 279: }
! 280:
! 281: METHOD(public_key_t, destroy, void,
! 282: private_bliss_public_key_t *this)
! 283: {
! 284: if (ref_put(&this->ref))
! 285: {
! 286: lib->encoding->clear_cache(lib->encoding, this);
! 287: free(this->A);
! 288: free(this->Ar);
! 289: free(this);
! 290: }
! 291: }
! 292:
! 293: /**
! 294: * ASN.1 definition of a BLISS public key
! 295: */
! 296: static const asn1Object_t pubkeyObjects[] = {
! 297: { 0, "subjectPublicKeyInfo",ASN1_SEQUENCE, ASN1_OBJ }, /* 0 */
! 298: { 1, "algorithm", ASN1_EOC, ASN1_RAW }, /* 1 */
! 299: { 1, "subjectPublicKey", ASN1_BIT_STRING, ASN1_BODY }, /* 2 */
! 300: { 0, "exit", ASN1_EOC, ASN1_EXIT }
! 301: };
! 302: #define BLISS_SUBJECT_PUBLIC_KEY_ALGORITHM 1
! 303: #define BLISS_SUBJECT_PUBLIC_KEY 2
! 304:
! 305: /**
! 306: * See header.
! 307: */
! 308: bliss_public_key_t *bliss_public_key_load(key_type_t type, va_list args)
! 309: {
! 310: private_bliss_public_key_t *this;
! 311: chunk_t blob = chunk_empty, object, param;
! 312: asn1_parser_t *parser;
! 313: bool success = FALSE;
! 314: int objectID, oid, i;
! 315: uint32_t r2;
! 316:
! 317: while (TRUE)
! 318: {
! 319: switch (va_arg(args, builder_part_t))
! 320: {
! 321: case BUILD_BLOB_ASN1_DER:
! 322: blob = va_arg(args, chunk_t);
! 323: continue;
! 324: case BUILD_END:
! 325: break;
! 326: default:
! 327: return NULL;
! 328: }
! 329: break;
! 330: }
! 331:
! 332: if (blob.len == 0)
! 333: {
! 334: return NULL;
! 335: }
! 336:
! 337: INIT(this,
! 338: .public = {
! 339: .key = {
! 340: .get_type = _get_type,
! 341: .verify = _verify,
! 342: .encrypt = _encrypt_,
! 343: .equals = public_key_equals,
! 344: .get_keysize = _get_keysize,
! 345: .get_fingerprint = _get_fingerprint,
! 346: .has_fingerprint = public_key_has_fingerprint,
! 347: .get_encoding = _get_encoding,
! 348: .get_ref = _get_ref,
! 349: .destroy = _destroy,
! 350: },
! 351: },
! 352: .ref = 1,
! 353: );
! 354:
! 355: parser = asn1_parser_create(pubkeyObjects, blob);
! 356:
! 357: while (parser->iterate(parser, &objectID, &object))
! 358: {
! 359: switch (objectID)
! 360: {
! 361: case BLISS_SUBJECT_PUBLIC_KEY_ALGORITHM:
! 362: {
! 363: oid = asn1_parse_algorithmIdentifier(object,
! 364: parser->get_level(parser)+1, ¶m);
! 365: if (oid != OID_BLISS_PUBLICKEY)
! 366: {
! 367: goto end;
! 368: }
! 369: if (!asn1_parse_simple_object(¶m, ASN1_OID,
! 370: parser->get_level(parser)+3, "blissKeyType"))
! 371: {
! 372: goto end;
! 373: }
! 374: oid = asn1_known_oid(param);
! 375: if (oid == OID_UNKNOWN)
! 376: {
! 377: goto end;
! 378: }
! 379: this->set = bliss_param_set_get_by_oid(oid);
! 380: if (this->set == NULL)
! 381: {
! 382: goto end;
! 383: }
! 384: break;
! 385: }
! 386: case BLISS_SUBJECT_PUBLIC_KEY:
! 387: if (!bliss_public_key_from_asn1(object, this->set, &this->A))
! 388: {
! 389: goto end;
! 390: }
! 391: this->Ar = malloc(this->set->n * sizeof(uint32_t));
! 392: r2 = this->set->fft_params->r2;
! 393:
! 394: for (i = 0; i < this->set->n; i++)
! 395: {
! 396: this->Ar[i] = ntt_fft_mreduce(this->A[i] * r2,
! 397: this->set->fft_params);
! 398: }
! 399: break;
! 400: }
! 401: }
! 402: success = parser->success(parser);
! 403:
! 404: end:
! 405: parser->destroy(parser);
! 406: if (!success)
! 407: {
! 408: destroy(this);
! 409: return NULL;
! 410: }
! 411:
! 412: return &this->public;
! 413: }
! 414:
! 415: /**
! 416: * See header.
! 417: */
! 418: bool bliss_public_key_from_asn1(chunk_t object, const bliss_param_set_t *set,
! 419: uint32_t **pubkey)
! 420: {
! 421: bliss_bitpacker_t *packer;
! 422: uint32_t coefficient;
! 423: uint16_t needed_bits;
! 424: int i;
! 425:
! 426: /* skip initial bit string octet defining unused bits */
! 427: object = chunk_skip(object, 1);
! 428:
! 429: needed_bits = set->n * set->q_bits;
! 430:
! 431: if (8 * object.len < needed_bits)
! 432: {
! 433: return FALSE;
! 434: }
! 435: *pubkey = malloc(set->n * sizeof(uint32_t));
! 436:
! 437: packer = bliss_bitpacker_create_from_data(object);
! 438:
! 439: for (i = 0; i < set->n; i++)
! 440: {
! 441: packer->read_bits(packer, &coefficient, set->q_bits);
! 442: if (coefficient >= set->q)
! 443: {
! 444: packer->destroy(packer);
! 445: return FALSE;
! 446: }
! 447: (*pubkey)[i] = coefficient;
! 448: }
! 449: packer->destroy(packer);
! 450:
! 451: return TRUE;
! 452: }
! 453:
! 454: /**
! 455: * See header.
! 456: */
! 457: chunk_t bliss_public_key_encode(uint32_t *pubkey, const bliss_param_set_t *set)
! 458: {
! 459: bliss_bitpacker_t *packer;
! 460: chunk_t encoding;
! 461: int i;
! 462:
! 463: packer = bliss_bitpacker_create(set->n * set->q_bits);
! 464:
! 465: for (i = 0; i < set->n; i++)
! 466: {
! 467: packer->write_bits(packer, pubkey[i], set->q_bits);
! 468: }
! 469: encoding = packer->extract_buf(packer);
! 470: packer->destroy(packer);
! 471:
! 472: return encoding;
! 473: }
! 474:
! 475: /**
! 476: * See header.
! 477: */
! 478: chunk_t bliss_public_key_info_encode(int oid, uint32_t *pubkey,
! 479: const bliss_param_set_t *set)
! 480: {
! 481: chunk_t encoding, pubkey_encoding;
! 482:
! 483: pubkey_encoding = bliss_public_key_encode(pubkey, set);
! 484:
! 485: encoding = asn1_wrap(ASN1_SEQUENCE, "mm",
! 486: asn1_wrap(ASN1_SEQUENCE, "mm",
! 487: asn1_build_known_oid(OID_BLISS_PUBLICKEY),
! 488: asn1_build_known_oid(oid)),
! 489: asn1_bitstring("m", pubkey_encoding));
! 490:
! 491: return encoding;
! 492: }
! 493:
! 494: /**
! 495: * See header.
! 496: */
! 497: bool bliss_public_key_fingerprint(int oid, uint32_t *pubkey,
! 498: const bliss_param_set_t *set,
! 499: cred_encoding_type_t type, chunk_t *fp)
! 500: {
! 501: hasher_t *hasher;
! 502: chunk_t key;
! 503:
! 504: switch (type)
! 505: {
! 506: case KEYID_PUBKEY_SHA1:
! 507: key = bliss_public_key_encode(pubkey, set);
! 508: break;
! 509: case KEYID_PUBKEY_INFO_SHA1:
! 510: key = bliss_public_key_info_encode(oid, pubkey, set);
! 511: break;
! 512: default:
! 513: return FALSE;
! 514: }
! 515:
! 516: hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1);
! 517: if (!hasher || !hasher->allocate_hash(hasher, key, fp))
! 518: {
! 519: DBG1(DBG_LIB, "SHA1 hash algorithm not supported, fingerprinting failed");
! 520: DESTROY_IF(hasher);
! 521: free(key.ptr);
! 522:
! 523: return FALSE;
! 524: }
! 525: hasher->destroy(hasher);
! 526: free(key.ptr);
! 527:
! 528: return TRUE;
! 529: }
! 530:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>