Annotation of embedaddon/strongswan/src/libstrongswan/plugins/pkcs1/pkcs1_builder.c, revision 1.1
1.1 ! misho 1: /*
! 2: * Copyright (C) 2008-2016 Tobias Brunner
! 3: * Copyright (C) 2008-2009 Martin Willi
! 4: * Copyright (C) 2000-2008 Andreas Steffen
! 5: * HSR Hochschule fuer Technik Rapperswil
! 6: *
! 7: * This program is free software; you can redistribute it and/or modify it
! 8: * under the terms of the GNU General Public License as published by the
! 9: * Free Software Foundation; either version 2 of the License, or (at your
! 10: * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
! 11: *
! 12: * This program is distributed in the hope that it will be useful, but
! 13: * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
! 14: * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
! 15: * for more details.
! 16: */
! 17:
! 18: #include "pkcs1_builder.h"
! 19:
! 20: #include <utils/debug.h>
! 21: #include <asn1/oid.h>
! 22: #include <asn1/asn1.h>
! 23: #include <asn1/asn1_parser.h>
! 24: #include <credentials/keys/private_key.h>
! 25:
! 26: /**
! 27: * ASN.1 definition of a subjectPublicKeyInfo structure
! 28: */
! 29: static const asn1Object_t pkinfoObjects[] = {
! 30: { 0, "subjectPublicKeyInfo",ASN1_SEQUENCE, ASN1_NONE }, /* 0 */
! 31: { 1, "algorithm", ASN1_EOC, ASN1_RAW }, /* 1 */
! 32: { 1, "subjectPublicKey", ASN1_BIT_STRING, ASN1_BODY }, /* 2 */
! 33: { 0, "exit", ASN1_EOC, ASN1_EXIT }
! 34: };
! 35: #define PKINFO_SUBJECT_PUBLIC_KEY_ALGORITHM 1
! 36: #define PKINFO_SUBJECT_PUBLIC_KEY 2
! 37:
! 38: /**
! 39: * Load a generic public key from an ASN.1 encoded blob
! 40: */
! 41: static public_key_t *parse_public_key(chunk_t blob)
! 42: {
! 43: asn1_parser_t *parser;
! 44: chunk_t object;
! 45: int objectID;
! 46: public_key_t *key = NULL;
! 47: key_type_t type = KEY_ANY;
! 48:
! 49: parser = asn1_parser_create(pkinfoObjects, blob);
! 50:
! 51: while (parser->iterate(parser, &objectID, &object))
! 52: {
! 53: switch (objectID)
! 54: {
! 55: case PKINFO_SUBJECT_PUBLIC_KEY_ALGORITHM:
! 56: {
! 57: int oid = asn1_parse_algorithmIdentifier(object,
! 58: parser->get_level(parser)+1, NULL);
! 59:
! 60: if (oid == OID_RSA_ENCRYPTION || oid == OID_RSAES_OAEP ||
! 61: oid == OID_RSASSA_PSS)
! 62: {
! 63: /* TODO: we should parse parameters for PSS and pass them
! 64: * (and the type), or the complete subjectPublicKeyInfo,
! 65: * along so we can treat these as restrictions when
! 66: * generating signatures with the associated private key */
! 67: type = KEY_RSA;
! 68: }
! 69: else if (oid == OID_EC_PUBLICKEY)
! 70: {
! 71: /* Need the whole subjectPublicKeyInfo for EC public keys */
! 72: key = lib->creds->create(lib->creds, CRED_PUBLIC_KEY,
! 73: KEY_ECDSA, BUILD_BLOB_ASN1_DER, blob, BUILD_END);
! 74: goto end;
! 75: }
! 76: else if (oid == OID_BLISS_PUBLICKEY)
! 77: {
! 78: /* Need the whole subjectPublicKeyInfo for BLISS public keys */
! 79: key = lib->creds->create(lib->creds, CRED_PUBLIC_KEY,
! 80: KEY_BLISS, BUILD_BLOB_ASN1_DER, blob, BUILD_END);
! 81: goto end;
! 82: }
! 83: else if (oid == OID_ED25519)
! 84: {
! 85: /* Need the whole subjectPublicKeyInfo for Ed25519 public keys */
! 86: key = lib->creds->create(lib->creds, CRED_PUBLIC_KEY,
! 87: KEY_ED25519, BUILD_BLOB_ASN1_DER, blob, BUILD_END);
! 88: goto end;
! 89: }
! 90: else if (oid == OID_ED448)
! 91: {
! 92: /* Need the whole subjectPublicKeyInfo for Ed448 public keys */
! 93: key = lib->creds->create(lib->creds, CRED_PUBLIC_KEY,
! 94: KEY_ED448, BUILD_BLOB_ASN1_DER, blob, BUILD_END);
! 95: goto end;
! 96: }
! 97: else
! 98: {
! 99: /* key type not supported */
! 100: goto end;
! 101: }
! 102: break;
! 103: }
! 104: case PKINFO_SUBJECT_PUBLIC_KEY:
! 105: if (object.len > 0 && *object.ptr == 0x00)
! 106: {
! 107: /* skip initial bit string octet defining 0 unused bits */
! 108: object = chunk_skip(object, 1);
! 109: }
! 110: DBG2(DBG_ASN, "-- > --");
! 111: key = lib->creds->create(lib->creds, CRED_PUBLIC_KEY, type,
! 112: BUILD_BLOB_ASN1_DER, object, BUILD_END);
! 113: DBG2(DBG_ASN, "-- < --");
! 114: break;
! 115: }
! 116: }
! 117:
! 118: end:
! 119: parser->destroy(parser);
! 120: return key;
! 121: }
! 122:
! 123: /**
! 124: * ASN.1 definition of RSApublicKey
! 125: */
! 126: static const asn1Object_t pubkeyObjects[] = {
! 127: { 0, "RSAPublicKey", ASN1_SEQUENCE, ASN1_OBJ }, /* 0 */
! 128: { 1, "modulus", ASN1_INTEGER, ASN1_BODY }, /* 1 */
! 129: { 1, "publicExponent", ASN1_INTEGER, ASN1_BODY }, /* 2 */
! 130: { 0, "exit", ASN1_EOC, ASN1_EXIT }
! 131: };
! 132: #define PUB_KEY_RSA_PUBLIC_KEY 0
! 133: #define PUB_KEY_MODULUS 1
! 134: #define PUB_KEY_EXPONENT 2
! 135:
! 136: /**
! 137: * Load a RSA public key from an ASN.1 encoded blob.
! 138: */
! 139: static public_key_t *parse_rsa_public_key(chunk_t blob)
! 140: {
! 141: chunk_t n, e;
! 142: asn1_parser_t *parser;
! 143: chunk_t object;
! 144: int objectID;
! 145: bool success = FALSE;
! 146:
! 147: parser = asn1_parser_create(pubkeyObjects, blob);
! 148:
! 149: while (parser->iterate(parser, &objectID, &object))
! 150: {
! 151: switch (objectID)
! 152: {
! 153: case PUB_KEY_MODULUS:
! 154: n = object;
! 155: break;
! 156: case PUB_KEY_EXPONENT:
! 157: e = object;
! 158: break;
! 159: }
! 160: }
! 161: success = parser->success(parser);
! 162: parser->destroy(parser);
! 163:
! 164: if (!success)
! 165: {
! 166: return NULL;
! 167: }
! 168: return lib->creds->create(lib->creds, CRED_PUBLIC_KEY, KEY_RSA,
! 169: BUILD_RSA_MODULUS, n, BUILD_RSA_PUB_EXP, e, BUILD_END);
! 170: }
! 171:
! 172: /**
! 173: * ASN.1 definition of a PKCS#1 RSA private key
! 174: */
! 175: static const asn1Object_t privkeyObjects[] = {
! 176: { 0, "RSAPrivateKey", ASN1_SEQUENCE, ASN1_NONE }, /* 0 */
! 177: { 1, "version", ASN1_INTEGER, ASN1_BODY }, /* 1 */
! 178: { 1, "modulus", ASN1_INTEGER, ASN1_BODY }, /* 2 */
! 179: { 1, "publicExponent", ASN1_INTEGER, ASN1_BODY }, /* 3 */
! 180: { 1, "privateExponent", ASN1_INTEGER, ASN1_BODY }, /* 4 */
! 181: { 1, "prime1", ASN1_INTEGER, ASN1_BODY }, /* 5 */
! 182: { 1, "prime2", ASN1_INTEGER, ASN1_BODY }, /* 6 */
! 183: { 1, "exponent1", ASN1_INTEGER, ASN1_BODY }, /* 7 */
! 184: { 1, "exponent2", ASN1_INTEGER, ASN1_BODY }, /* 8 */
! 185: { 1, "coefficient", ASN1_INTEGER, ASN1_BODY }, /* 9 */
! 186: { 1, "otherPrimeInfos", ASN1_SEQUENCE, ASN1_OPT |
! 187: ASN1_LOOP }, /* 10 */
! 188: { 2, "otherPrimeInfo", ASN1_SEQUENCE, ASN1_NONE }, /* 11 */
! 189: { 3, "prime", ASN1_INTEGER, ASN1_BODY }, /* 12 */
! 190: { 3, "exponent", ASN1_INTEGER, ASN1_BODY }, /* 13 */
! 191: { 3, "coefficient", ASN1_INTEGER, ASN1_BODY }, /* 14 */
! 192: { 1, "end opt or loop", ASN1_EOC, ASN1_END }, /* 15 */
! 193: { 0, "exit", ASN1_EOC, ASN1_EXIT }
! 194: };
! 195: #define PRIV_KEY_VERSION 1
! 196: #define PRIV_KEY_MODULUS 2
! 197: #define PRIV_KEY_PUB_EXP 3
! 198: #define PRIV_KEY_PRIV_EXP 4
! 199: #define PRIV_KEY_PRIME1 5
! 200: #define PRIV_KEY_PRIME2 6
! 201: #define PRIV_KEY_EXP1 7
! 202: #define PRIV_KEY_EXP2 8
! 203: #define PRIV_KEY_COEFF 9
! 204:
! 205: /**
! 206: * Load a RSA private key from a ASN1 encoded blob.
! 207: */
! 208: static private_key_t *parse_rsa_private_key(chunk_t blob)
! 209: {
! 210: chunk_t n, e, d, p, q, exp1, exp2, coeff;
! 211: asn1_parser_t *parser;
! 212: chunk_t object;
! 213: int objectID ;
! 214: bool success = FALSE;
! 215:
! 216: parser = asn1_parser_create(privkeyObjects, blob);
! 217: parser->set_flags(parser, FALSE, TRUE);
! 218:
! 219: while (parser->iterate(parser, &objectID, &object))
! 220: {
! 221: switch (objectID)
! 222: {
! 223: case PRIV_KEY_VERSION:
! 224: if (object.len > 0 && *object.ptr != 0)
! 225: {
! 226: goto end;
! 227: }
! 228: break;
! 229: case PRIV_KEY_MODULUS:
! 230: n = object;
! 231: break;
! 232: case PRIV_KEY_PUB_EXP:
! 233: e = object;
! 234: break;
! 235: case PRIV_KEY_PRIV_EXP:
! 236: d = object;
! 237: break;
! 238: case PRIV_KEY_PRIME1:
! 239: p = object;
! 240: break;
! 241: case PRIV_KEY_PRIME2:
! 242: q = object;
! 243: break;
! 244: case PRIV_KEY_EXP1:
! 245: exp1 = object;
! 246: break;
! 247: case PRIV_KEY_EXP2:
! 248: exp2 = object;
! 249: break;
! 250: case PRIV_KEY_COEFF:
! 251: coeff = object;
! 252: break;
! 253: }
! 254: }
! 255: success = parser->success(parser);
! 256:
! 257: end:
! 258: parser->destroy(parser);
! 259: if (!success)
! 260: {
! 261: return NULL;
! 262: }
! 263: return lib->creds->create(lib->creds, CRED_PRIVATE_KEY, KEY_RSA,
! 264: BUILD_RSA_MODULUS, n, BUILD_RSA_PUB_EXP, e, BUILD_RSA_PRIV_EXP, d,
! 265: BUILD_RSA_PRIME1, p, BUILD_RSA_PRIME2, q, BUILD_RSA_EXP1, exp1,
! 266: BUILD_RSA_EXP2, exp2, BUILD_RSA_COEFF, coeff, BUILD_END);
! 267: }
! 268:
! 269: /**
! 270: * Check if the ASN.1 structure looks like an EC private key according to
! 271: * RFC 5915.
! 272: *
! 273: * ECPrivateKey :=: SEQUENCE {
! 274: * version INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1),
! 275: * privateKey OCTET STRING,
! 276: * parameters [0] ECParameters {{ NamedCurve }} OPTIONAL,
! 277: * publicKey [1] BIT STRING OPTIONAL
! 278: * }
! 279: *
! 280: * While the parameters and publicKey fields are OPTIONAL, RFC 5915 says that
! 281: * parameters MUST be included (an errata clarifies this, so this is only the
! 282: * case for plain private keys, not encoded in PKCS#8) and publicKey SHOULD be.
! 283: */
! 284: static bool is_ec_private_key(chunk_t blob)
! 285: {
! 286: chunk_t data;
! 287: return asn1_unwrap(&blob, &blob) == ASN1_SEQUENCE &&
! 288: asn1_unwrap(&blob, &data) == ASN1_INTEGER &&
! 289: asn1_parse_integer_uint64(data) == 1 &&
! 290: asn1_unwrap(&blob, &data) == ASN1_OCTET_STRING &&
! 291: asn1_unwrap(&blob, &data) == ASN1_CONTEXT_C_0 &&
! 292: asn1_unwrap(&data, &data) == ASN1_OID &&
! 293: (!blob.len || (asn1_unwrap(&blob, &data) == ASN1_CONTEXT_C_1));
! 294: }
! 295:
! 296: /**
! 297: * Check if the ASN.1 structure looks like a BLISS private key.
! 298: */
! 299: static bool is_bliss_private_key(chunk_t blob)
! 300: {
! 301: chunk_t data;
! 302: return asn1_unwrap(&blob, &blob) == ASN1_SEQUENCE &&
! 303: asn1_unwrap(&blob, &data) == ASN1_OID &&
! 304: asn1_unwrap(&blob, &data) == ASN1_BIT_STRING &&
! 305: asn1_unwrap(&blob, &data) == ASN1_BIT_STRING &&
! 306: asn1_unwrap(&blob, &data) == ASN1_BIT_STRING;
! 307: }
! 308:
! 309: /**
! 310: * Load a private key from an ASN.1 encoded blob trying to detect the type
! 311: * automatically.
! 312: */
! 313: static private_key_t *parse_private_key(chunk_t blob)
! 314: {
! 315: if (is_ec_private_key(blob))
! 316: {
! 317: return lib->creds->create(lib->creds, CRED_PRIVATE_KEY, KEY_ECDSA,
! 318: BUILD_BLOB_ASN1_DER, blob, BUILD_END);
! 319: }
! 320: else if (is_bliss_private_key(blob))
! 321: {
! 322: return lib->creds->create(lib->creds, CRED_PRIVATE_KEY, KEY_ECDSA,
! 323: BUILD_BLOB_ASN1_DER, blob, BUILD_END);
! 324: }
! 325: return parse_rsa_private_key(blob);
! 326: }
! 327:
! 328: /**
! 329: * See header.
! 330: */
! 331: public_key_t *pkcs1_public_key_load(key_type_t type, va_list args)
! 332: {
! 333: chunk_t blob = chunk_empty;
! 334:
! 335: while (TRUE)
! 336: {
! 337: switch (va_arg(args, builder_part_t))
! 338: {
! 339: case BUILD_BLOB_ASN1_DER:
! 340: blob = va_arg(args, chunk_t);
! 341: continue;
! 342: case BUILD_END:
! 343: break;
! 344: default:
! 345: return NULL;
! 346: }
! 347: break;
! 348: }
! 349: switch (type)
! 350: {
! 351: case KEY_ANY:
! 352: return parse_public_key(blob);
! 353: case KEY_RSA:
! 354: return parse_rsa_public_key(blob);
! 355: default:
! 356: return NULL;
! 357: }
! 358: }
! 359:
! 360: /**
! 361: * See header.
! 362: */
! 363: private_key_t *pkcs1_private_key_load(key_type_t type, va_list args)
! 364: {
! 365: chunk_t blob = chunk_empty;
! 366:
! 367: while (TRUE)
! 368: {
! 369: switch (va_arg(args, builder_part_t))
! 370: {
! 371: case BUILD_BLOB_ASN1_DER:
! 372: blob = va_arg(args, chunk_t);
! 373: continue;
! 374: case BUILD_END:
! 375: break;
! 376: default:
! 377: return NULL;
! 378: }
! 379: break;
! 380: }
! 381: switch (type)
! 382: {
! 383: case KEY_ANY:
! 384: return parse_private_key(blob);
! 385: case KEY_RSA:
! 386: return parse_rsa_private_key(blob);
! 387: default:
! 388: return NULL;
! 389: }
! 390: }
! 391:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>