Return to curve25519_public_key.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / strongswan / src / libstrongswan / plugins / curve25519 |
1.1 misho 1: /* 2: * Copyright (C) 2018 Tobias Brunner 3: * Copyright (C) 2016 Andreas Steffen 4: * HSR Hochschule fuer Technik Rapperswil 5: * 6: * This program is free software; you can redistribute it and/or modify it 7: * under the terms of the GNU General Public License as published by the 8: * Free Software Foundation; either version 2 of the License, or (at your 9: * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. 10: * 11: * This program is distributed in the hope that it will be useful, but 12: * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 13: * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14: * for more details. 15: */ 16: 17: #include "curve25519_public_key.h" 18: #include "ref10/ref10.h" 19: 20: #include <asn1/asn1.h> 21: #include <asn1/asn1_parser.h> 22: #include <asn1/oid.h> 23: 24: typedef struct private_curve25519_public_key_t private_curve25519_public_key_t; 25: 26: /** 27: * Private data structure with signing context. 28: */ 29: struct private_curve25519_public_key_t { 30: /** 31: * Public interface for this signer. 32: */ 33: curve25519_public_key_t public; 34: 35: /** 36: * Ed25519 public key 37: */ 38: chunk_t pubkey; 39: 40: /** 41: * Reference counter 42: */ 43: refcount_t ref; 44: }; 45: 46: METHOD(public_key_t, get_type, key_type_t, 47: private_curve25519_public_key_t *this) 48: { 49: return KEY_ED25519; 50: } 51: 52: /* L = 2^252+27742317777372353535851937790883648493 in little-endian form */ 53: static chunk_t curve25519_order = chunk_from_chars( 54: 0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58, 55: 0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde, 0x14, 56: 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 57: 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10); 58: 59: METHOD(public_key_t, verify, bool, 60: private_curve25519_public_key_t *this, signature_scheme_t scheme, 61: void *params, chunk_t data, chunk_t signature) 62: { 63: hasher_t *hasher; 64: uint8_t d = 0, k[HASH_SIZE_SHA512], r[32], *sig; 65: int i; 66: ge_p3 A; 67: ge_p2 R; 68: 69: if (scheme != SIGN_ED25519) 70: { 71: DBG1(DBG_LIB, "signature scheme %N not supported by Ed25519", 72: signature_scheme_names, scheme); 73: return FALSE; 74: } 75: 76: if (signature.len != 64) 77: { 78: DBG1(DBG_LIB, "size of Ed25519 signature is not 64 bytes"); 79: return FALSE; 80: } 81: sig = signature.ptr; 82: 83: if (sig[63] & 0xe0) 84: { 85: DBG1(DBG_LIB, "the three most significant bits of Ed25519 signature " 86: "are not zero"); 87: return FALSE; 88: } 89: 90: if (ge_frombytes_negate_vartime(&A, this->pubkey.ptr) != 0) 91: { 92: return FALSE; 93: } 94: 95: /* check for all-zeroes public key */ 96: for (i = 0; i < 32; i++) 97: { 98: d |= this->pubkey.ptr[i]; 99: } 100: if (!d) 101: { 102: return FALSE; 103: } 104: /* make sure 0 <= s < L, as per RFC 8032, section 5.1.7 to prevent signature 105: * malleability. Due to the three-bit check above (forces s < 2^253) there 106: * is not that much room, but adding L once works with most signatures */ 107: for (i = 31; ; i--) 108: { 109: if (sig[i+32] < curve25519_order.ptr[i]) 110: { 111: break; 112: } 113: else if (sig[i+32] > curve25519_order.ptr[i] || i == 0) 114: { 115: return FALSE; 116: } 117: } 118: 119: hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA512); 120: if (!hasher) 121: { 122: return FALSE; 123: } 124: if (!hasher->get_hash(hasher, chunk_create(sig, 32), NULL) || 125: !hasher->get_hash(hasher, this->pubkey, NULL) || 126: !hasher->get_hash(hasher, data, k)) 127: { 128: hasher->destroy(hasher); 129: return FALSE; 130: } 131: hasher->destroy(hasher); 132: 133: sc_reduce(k); 134: ge_double_scalarmult_vartime(&R, k, &A, sig + 32); 135: ge_tobytes(r, &R); 136: 137: return memeq_const(sig, r, 32); 138: } 139: 140: METHOD(public_key_t, encrypt_, bool, 141: private_curve25519_public_key_t *this, encryption_scheme_t scheme, 142: chunk_t plain, chunk_t *crypto) 143: { 144: DBG1(DBG_LIB, "encryption scheme %N not supported", encryption_scheme_names, 145: scheme); 146: return FALSE; 147: } 148: 149: METHOD(public_key_t, get_keysize, int, 150: private_curve25519_public_key_t *this) 151: { 152: return 8 * ED25519_KEY_LEN; 153: } 154: 155: METHOD(public_key_t, get_encoding, bool, 156: private_curve25519_public_key_t *this, cred_encoding_type_t type, 157: chunk_t *encoding) 158: { 159: bool success = TRUE; 160: 161: *encoding = curve25519_public_key_info_encode(this->pubkey); 162: 163: if (type != PUBKEY_SPKI_ASN1_DER) 164: { 165: chunk_t asn1_encoding = *encoding; 166: 167: success = lib->encoding->encode(lib->encoding, type, 168: NULL, encoding, CRED_PART_EDDSA_PUB_ASN1_DER, 169: asn1_encoding, CRED_PART_END); 170: chunk_clear(&asn1_encoding); 171: } 172: return success; 173: } 174: 175: METHOD(public_key_t, get_fingerprint, bool, 176: private_curve25519_public_key_t *this, cred_encoding_type_t type, 177: chunk_t *fp) 178: { 179: bool success; 180: 181: if (lib->encoding->get_cache(lib->encoding, type, this, fp)) 182: { 183: return TRUE; 184: } 185: success = curve25519_public_key_fingerprint(this->pubkey, type, fp); 186: if (success) 187: { 188: lib->encoding->cache(lib->encoding, type, this, *fp); 189: } 190: return success; 191: } 192: 193: METHOD(public_key_t, get_ref, public_key_t*, 194: private_curve25519_public_key_t *this) 195: { 196: ref_get(&this->ref); 197: return &this->public.key; 198: } 199: 200: METHOD(public_key_t, destroy, void, 201: private_curve25519_public_key_t *this) 202: { 203: if (ref_put(&this->ref)) 204: { 205: lib->encoding->clear_cache(lib->encoding, this); 206: free(this->pubkey.ptr); 207: free(this); 208: } 209: } 210: 211: /** 212: * ASN.1 definition of an Ed25519 public key 213: */ 214: static const asn1Object_t pubkeyObjects[] = { 215: { 0, "subjectPublicKeyInfo",ASN1_SEQUENCE, ASN1_NONE }, /* 0 */ 216: { 1, "algorithm", ASN1_EOC, ASN1_RAW }, /* 1 */ 217: { 1, "subjectPublicKey", ASN1_BIT_STRING, ASN1_BODY }, /* 2 */ 218: { 0, "exit", ASN1_EOC, ASN1_EXIT } 219: }; 220: 221: #define ED25519_SUBJECT_PUBLIC_KEY_ALGORITHM 1 222: #define ED25519_SUBJECT_PUBLIC_KEY 2 223: 224: /** 225: * Parse the ASN.1-encoded subjectPublicKeyInfo 226: */ 227: static bool parse_public_key_info(private_curve25519_public_key_t *this, 228: chunk_t blob) 229: { 230: asn1_parser_t *parser; 231: chunk_t object; 232: bool success = FALSE; 233: int objectID, oid; 234: 235: parser = asn1_parser_create(pubkeyObjects, blob); 236: 237: while (parser->iterate(parser, &objectID, &object)) 238: { 239: switch (objectID) 240: { 241: case ED25519_SUBJECT_PUBLIC_KEY_ALGORITHM: 242: { 243: oid = asn1_parse_algorithmIdentifier(object, 244: parser->get_level(parser) + 1, NULL); 245: if (oid != OID_ED25519) 246: { 247: goto end; 248: } 249: break; 250: } 251: case ED25519_SUBJECT_PUBLIC_KEY: 252: { 253: /* encoded as an ASN1 BIT STRING */ 254: if (object.len != 1 + ED25519_KEY_LEN) 255: { 256: goto end; 257: } 258: this->pubkey = chunk_clone(chunk_skip(object, 1)); 259: break; 260: } 261: } 262: } 263: success = parser->success(parser); 264: 265: end: 266: parser->destroy(parser); 267: return success; 268: } 269: 270: /** 271: * See header. 272: */ 273: curve25519_public_key_t *curve25519_public_key_load(key_type_t type, 274: va_list args) 275: { 276: private_curve25519_public_key_t *this; 277: chunk_t asn1 = chunk_empty, blob = chunk_empty; 278: 279: while (TRUE) 280: { 281: switch (va_arg(args, builder_part_t)) 282: { 283: case BUILD_BLOB_ASN1_DER: 284: asn1 = va_arg(args, chunk_t); 285: continue; 286: case BUILD_EDDSA_PUB: 287: blob = va_arg(args, chunk_t); 288: continue; 289: case BUILD_END: 290: break; 291: default: 292: return NULL; 293: } 294: break; 295: } 296: 297: INIT(this, 298: .public = { 299: .key = { 300: .get_type = _get_type, 301: .verify = _verify, 302: .encrypt = _encrypt_, 303: .equals = public_key_equals, 304: .get_keysize = _get_keysize, 305: .get_fingerprint = _get_fingerprint, 306: .has_fingerprint = public_key_has_fingerprint, 307: .get_encoding = _get_encoding, 308: .get_ref = _get_ref, 309: .destroy = _destroy, 310: }, 311: }, 312: .ref = 1, 313: ); 314: 315: if (blob.len == ED25519_KEY_LEN) 316: { 317: this->pubkey = chunk_clone(blob); 318: } 319: else if (!asn1.len || !parse_public_key_info(this, asn1)) 320: { 321: destroy(this); 322: return NULL; 323: } 324: return &this->public; 325: } 326: 327: /** 328: * See header. 329: */ 330: chunk_t curve25519_public_key_info_encode(chunk_t pubkey) 331: { 332: return asn1_wrap(ASN1_SEQUENCE, "mm", 333: asn1_wrap(ASN1_SEQUENCE, "m", 334: asn1_build_known_oid(OID_ED25519)), 335: asn1_bitstring("c", pubkey)); 336: } 337: 338: /** 339: * See header. 340: */ 341: bool curve25519_public_key_fingerprint(chunk_t pubkey, 342: cred_encoding_type_t type, chunk_t *fp) 343: { 344: hasher_t *hasher; 345: chunk_t key; 346: 347: switch (type) 348: { 349: case KEYID_PUBKEY_SHA1: 350: key = chunk_clone(pubkey); 351: break; 352: case KEYID_PUBKEY_INFO_SHA1: 353: key = curve25519_public_key_info_encode(pubkey); 354: break; 355: default: 356: return FALSE; 357: } 358: 359: hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1); 360: if (!hasher || !hasher->allocate_hash(hasher, key, fp)) 361: { 362: DBG1(DBG_LIB, "SHA1 hash algorithm not supported, " 363: "fingerprinting failed"); 364: DESTROY_IF(hasher); 365: free(key.ptr); 366: return FALSE; 367: } 368: hasher->destroy(hasher); 369: free(key.ptr); 370: return TRUE; 371: }