diff options
Diffstat (limited to 'src/libstrongswan/crypto')
56 files changed, 1194 insertions, 16409 deletions
diff --git a/src/libstrongswan/crypto/ac.c b/src/libstrongswan/crypto/ac.c deleted file mode 100644 index 641ce5d64..000000000 --- a/src/libstrongswan/crypto/ac.c +++ /dev/null @@ -1,636 +0,0 @@ -/** - * @file ac.c - * - * @brief Implementation of x509ac_t. - * - */ - -/* - * Copyright (C) 2002 Ueli Galizzi, Ariane Seiler - * Copyright (C) 2003 Martin Berner, Lukas Suter - * Copyright (C) 2007 Andreas Steffen, Hochschule fuer Technik Rapperswil - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * RCSID $Id: ac.c 3355 2007-11-20 12:06:40Z martin $ - */ - -#include <string.h> -#include <stdio.h> - -#include <library.h> -#include <debug.h> - -#include <asn1/asn1.h> -#include <asn1/pem.h> -#include <crypto/x509.h> -#include <crypto/ietf_attr_list.h> -#include <utils/identification.h> -#include <utils/linked_list.h> -#include <utils/lexparser.h> - -#include "ac.h" - -#define ACERT_WARNING_INTERVAL 1 /* day */ - -typedef struct private_x509ac_t private_x509ac_t; - -/** - * Private data of a x509ac_t object. - */ -struct private_x509ac_t { - /** - * Public interface for this attribute certificate. - */ - x509ac_t public; - - /** - * Time when attribute certificate was installed - */ - time_t installed; - - /** - * X.509 attribute certificate in DER format - */ - chunk_t certificate; - - /** - * X.509 attribute certificate body over which signature is computed - */ - chunk_t certificateInfo; - - /** - * Version of the X.509 attribute certificate - */ - u_int version; - - /** - * Serial number of the X.509 attribute certificate - */ - chunk_t serialNumber; - - /** - * ID representing the issuer of the holder certificate - */ - identification_t *holderIssuer; - - /** - * Serial number of the holder certificate - */ - chunk_t holderSerial; - - /** - * ID representing the holder - */ - identification_t *entityName; - - /** - * ID representing the attribute certificate issuer - */ - identification_t *issuerName; - - /** - * Signature algorithm - */ - int sigAlg; - - /** - * Start time of certificate validity - */ - time_t notBefore; - - /** - * End time of certificate validity - */ - time_t notAfter; - - /** - * List of charging attributes - */ - linked_list_t *charging; - - /** - * List of groub attributes - */ - linked_list_t *groups; - - /** - * Authority Key Identifier - */ - chunk_t authKeyID; - - /** - * Authority Key Serial Number - */ - chunk_t authKeySerialNumber; - - /** - * No revocation information available - */ - bool noRevAvail; - - /** - * Signature algorithm (must be identical to sigAlg) - */ - int algorithm; - - /** - * Signature - */ - chunk_t signature; -}; - -/** - * ASN.1 definition of roleSyntax - */ -static const asn1Object_t roleSyntaxObjects[] = -{ - { 0, "roleSyntax", ASN1_SEQUENCE, ASN1_NONE }, /* 0 */ - { 1, "roleAuthority", ASN1_CONTEXT_C_0, ASN1_OPT | - ASN1_OBJ }, /* 1 */ - { 1, "end opt", ASN1_EOC, ASN1_END }, /* 2 */ - { 1, "roleName", ASN1_CONTEXT_C_1, ASN1_OBJ } /* 3 */ -}; - -#define ROLE_ROOF 4 - -/** - * ASN.1 definition of an X509 attribute certificate - */ -static const asn1Object_t acObjects[] = -{ - { 0, "AttributeCertificate", ASN1_SEQUENCE, ASN1_OBJ }, /* 0 */ - { 1, "AttributeCertificateInfo", ASN1_SEQUENCE, ASN1_OBJ }, /* 1 */ - { 2, "version", ASN1_INTEGER, ASN1_DEF | - ASN1_BODY }, /* 2 */ - { 2, "holder", ASN1_SEQUENCE, ASN1_NONE }, /* 3 */ - { 3, "baseCertificateID", ASN1_CONTEXT_C_0, ASN1_OPT }, /* 4 */ - { 4, "issuer", ASN1_SEQUENCE, ASN1_OBJ }, /* 5 */ - { 4, "serial", ASN1_INTEGER, ASN1_BODY }, /* 6 */ - { 4, "issuerUID", ASN1_BIT_STRING, ASN1_OPT | - ASN1_BODY }, /* 7 */ - { 4, "end opt", ASN1_EOC, ASN1_END }, /* 8 */ - { 3, "end opt", ASN1_EOC, ASN1_END }, /* 9 */ - { 3, "entityName", ASN1_CONTEXT_C_1, ASN1_OPT | - ASN1_OBJ }, /* 10 */ - { 3, "end opt", ASN1_EOC, ASN1_END }, /* 11 */ - { 3, "objectDigestInfo", ASN1_CONTEXT_C_2, ASN1_OPT }, /* 12 */ - { 4, "digestedObjectType", ASN1_ENUMERATED, ASN1_BODY }, /* 13*/ - { 4, "otherObjectTypeID", ASN1_OID, ASN1_OPT | - ASN1_BODY }, /* 14 */ - { 4, "end opt", ASN1_EOC, ASN1_END }, /* 15*/ - { 4, "digestAlgorithm", ASN1_EOC, ASN1_RAW }, /* 16 */ - { 3, "end opt", ASN1_EOC, ASN1_END }, /* 17 */ - { 2, "v2Form", ASN1_CONTEXT_C_0, ASN1_NONE }, /* 18 */ - { 3, "issuerName", ASN1_SEQUENCE, ASN1_OPT | - ASN1_OBJ }, /* 19 */ - { 3, "end opt", ASN1_EOC, ASN1_END }, /* 20 */ - { 3, "baseCertificateID", ASN1_CONTEXT_C_0, ASN1_OPT }, /* 21 */ - { 4, "issuerSerial", ASN1_SEQUENCE, ASN1_NONE }, /* 22 */ - { 5, "issuer", ASN1_SEQUENCE, ASN1_OBJ }, /* 23 */ - { 5, "serial", ASN1_INTEGER, ASN1_BODY }, /* 24 */ - { 5, "issuerUID", ASN1_BIT_STRING, ASN1_OPT | - ASN1_BODY }, /* 25 */ - { 5, "end opt", ASN1_EOC, ASN1_END }, /* 26 */ - { 3, "end opt", ASN1_EOC, ASN1_END }, /* 27 */ - { 3, "objectDigestInfo", ASN1_CONTEXT_C_1, ASN1_OPT }, /* 28 */ - { 4, "digestInfo", ASN1_SEQUENCE, ASN1_OBJ }, /* 29 */ - { 5, "digestedObjectType", ASN1_ENUMERATED, ASN1_BODY }, /* 30 */ - { 5, "otherObjectTypeID", ASN1_OID, ASN1_OPT | - ASN1_BODY }, /* 31 */ - { 5, "end opt", ASN1_EOC, ASN1_END }, /* 32 */ - { 5, "digestAlgorithm", ASN1_EOC, ASN1_RAW }, /* 33 */ - { 3, "end opt", ASN1_EOC, ASN1_END }, /* 34 */ - { 2, "signature", ASN1_EOC, ASN1_RAW }, /* 35 */ - { 2, "serialNumber", ASN1_INTEGER, ASN1_BODY }, /* 36 */ - { 2, "attrCertValidityPeriod", ASN1_SEQUENCE, ASN1_NONE }, /* 37 */ - { 3, "notBeforeTime", ASN1_GENERALIZEDTIME, ASN1_BODY }, /* 38 */ - { 3, "notAfterTime", ASN1_GENERALIZEDTIME, ASN1_BODY }, /* 39 */ - { 2, "attributes", ASN1_SEQUENCE, ASN1_LOOP }, /* 40 */ - { 3, "attribute", ASN1_SEQUENCE, ASN1_NONE }, /* 41 */ - { 4, "type", ASN1_OID, ASN1_BODY }, /* 42 */ - { 4, "values", ASN1_SET, ASN1_LOOP }, /* 43 */ - { 5, "value", ASN1_EOC, ASN1_RAW }, /* 44 */ - { 4, "end loop", ASN1_EOC, ASN1_END }, /* 45 */ - { 2, "end loop", ASN1_EOC, ASN1_END }, /* 46 */ - { 2, "extensions", ASN1_SEQUENCE, ASN1_LOOP }, /* 47 */ - { 3, "extension", ASN1_SEQUENCE, ASN1_NONE }, /* 48 */ - { 4, "extnID", ASN1_OID, ASN1_BODY }, /* 49 */ - { 4, "critical", ASN1_BOOLEAN, ASN1_DEF | - ASN1_BODY }, /* 50 */ - { 4, "extnValue", ASN1_OCTET_STRING, ASN1_BODY }, /* 51 */ - { 2, "end loop", ASN1_EOC, ASN1_END }, /* 52 */ - { 1, "signatureAlgorithm", ASN1_EOC, ASN1_RAW }, /* 53 */ - { 1, "signatureValue", ASN1_BIT_STRING, ASN1_BODY } /* 54 */ -}; - -#define AC_OBJ_CERTIFICATE 0 -#define AC_OBJ_CERTIFICATE_INFO 1 -#define AC_OBJ_VERSION 2 -#define AC_OBJ_HOLDER_ISSUER 5 -#define AC_OBJ_HOLDER_SERIAL 6 -#define AC_OBJ_ENTITY_NAME 10 -#define AC_OBJ_ISSUER_NAME 19 -#define AC_OBJ_ISSUER 23 -#define AC_OBJ_SIG_ALG 35 -#define AC_OBJ_SERIAL_NUMBER 36 -#define AC_OBJ_NOT_BEFORE 38 -#define AC_OBJ_NOT_AFTER 39 -#define AC_OBJ_ATTRIBUTE_TYPE 42 -#define AC_OBJ_ATTRIBUTE_VALUE 44 -#define AC_OBJ_EXTN_ID 49 -#define AC_OBJ_CRITICAL 50 -#define AC_OBJ_EXTN_VALUE 51 -#define AC_OBJ_ALGORITHM 53 -#define AC_OBJ_SIGNATURE 54 -#define AC_OBJ_ROOF 55 - -/** - * Implements x509ac_t.is_valid - */ -static err_t is_valid(const private_x509ac_t *this, time_t *until) -{ - time_t current_time = time(NULL); - - DBG2(" not before : %T", &this->notBefore); - DBG2(" current time: %T", ¤t_time); - DBG2(" not after : %T", &this->notAfter); - - if (until != NULL && - (*until == UNDEFINED_TIME || this->notAfter < *until)) - { - *until = this->notAfter; - } - if (current_time < this->notBefore) - { - return "is not valid yet"; - } - if (current_time > this->notAfter) - { - return "has expired"; - } - DBG2(" attribute certificate is valid"); - return NULL; -} - -/** - * Implements x509ac_t.is_newer - */ -static bool is_newer(const private_x509ac_t *this, const private_x509ac_t *other) -{ - return this->notBefore > other->notBefore; -} - -/** - * Implements x509ac_t.equals_holder. - */ -static bool equals_holder(const private_x509ac_t *this, const private_x509ac_t *other) -{ - return this->holderIssuer->equals(this->holderIssuer, other->holderIssuer) - && chunk_equals(this->holderSerial, other->holderSerial); -} - -/** - * parses a directoryName - */ -static bool parse_directoryName(chunk_t blob, int level, bool implicit, identification_t **name) -{ - bool has_directoryName; - linked_list_t *list = linked_list_create(); - - x509_parse_generalNames(blob, level, implicit, list); - has_directoryName = list->get_count(list) > 0; - - if (has_directoryName) - { - iterator_t *iterator = list->create_iterator(list, TRUE); - identification_t *directoryName; - bool first = TRUE; - - while (iterator->iterate(iterator, (void**)&directoryName)) - { - if (first) - { - *name = directoryName; - first = FALSE; - } - else - { - DBG1("more than one directory name - first selected"); - directoryName->destroy(directoryName); - } - } - iterator->destroy(iterator); - } - else - { - DBG1("no directoryName found"); - } - - list->destroy(list); - return has_directoryName; -} - -/** - * parses roleSyntax - */ -static void parse_roleSyntax(chunk_t blob, int level0) -{ - asn1_ctx_t ctx; - chunk_t object; - u_int level; - int objectID = 0; - - asn1_init(&ctx, blob, level0, FALSE, FALSE); - while (objectID < ROLE_ROOF) - { - if (!extract_object(roleSyntaxObjects, &objectID, &object, &level, &ctx)) - { - return; - } - - switch (objectID) - { - default: - break; - } - objectID++; - } -} - -/** - * Parses an X.509 attribute certificate - */ -static bool parse_certificate(chunk_t blob, private_x509ac_t *this) -{ - asn1_ctx_t ctx; - bool critical; - chunk_t object; - u_int level; - int objectID = 0; - int type = OID_UNKNOWN; - int extn_oid = OID_UNKNOWN; - - asn1_init(&ctx, blob, 0, FALSE, FALSE); - while (objectID < AC_OBJ_ROOF) - { - if (!extract_object(acObjects, &objectID, &object, &level, &ctx)) - { - return FALSE; - } - - /* those objects which will parsed further need the next higher level */ - level++; - - switch (objectID) - { - case AC_OBJ_CERTIFICATE: - this->certificate = object; - break; - case AC_OBJ_CERTIFICATE_INFO: - this->certificateInfo = object; - break; - case AC_OBJ_VERSION: - this->version = (object.len) ? (1 + (u_int)*object.ptr) : 1; - DBG2(" v%d", this->version); - if (this->version != 2) - { - DBG1("v%d attribute certificates are not supported", this->version); - return FALSE; - } - break; - case AC_OBJ_HOLDER_ISSUER: - if (!parse_directoryName(object, level, FALSE, &this->holderIssuer)) - { - return FALSE; - } - break; - case AC_OBJ_HOLDER_SERIAL: - this->holderSerial = object; - break; - case AC_OBJ_ENTITY_NAME: - if (!parse_directoryName(object, level, TRUE, &this->entityName)) - { - return FALSE; - } - break; - case AC_OBJ_ISSUER_NAME: - if (!parse_directoryName(object, level, FALSE, &this->issuerName)) - { - return FALSE; - } - break; - case AC_OBJ_SIG_ALG: - this->sigAlg = parse_algorithmIdentifier(object, level, NULL); - break; - case AC_OBJ_SERIAL_NUMBER: - this->serialNumber = object; - break; - case AC_OBJ_NOT_BEFORE: - this->notBefore = asn1totime(&object, ASN1_GENERALIZEDTIME); - break; - case AC_OBJ_NOT_AFTER: - this->notAfter = asn1totime(&object, ASN1_GENERALIZEDTIME); - break; - case AC_OBJ_ATTRIBUTE_TYPE: - type = known_oid(object); - break; - case AC_OBJ_ATTRIBUTE_VALUE: - { - switch (type) - { - case OID_AUTHENTICATION_INFO: - DBG2(" need to parse authenticationInfo"); - break; - case OID_ACCESS_IDENTITY: - DBG2(" need to parse accessIdentity"); - break; - case OID_CHARGING_IDENTITY: - ietfAttr_list_create_from_chunk(object, this->charging, level); - break; - case OID_GROUP: - ietfAttr_list_create_from_chunk(object, this->groups, level); - break; - case OID_ROLE: - parse_roleSyntax(object, level); - break; - default: - break; - } - } - break; - case AC_OBJ_EXTN_ID: - extn_oid = known_oid(object); - break; - case AC_OBJ_CRITICAL: - critical = object.len && *object.ptr; - DBG2(" %s",(critical)?"TRUE":"FALSE"); - break; - case AC_OBJ_EXTN_VALUE: - { - switch (extn_oid) - { - case OID_CRL_DISTRIBUTION_POINTS: - DBG2(" need to parse crlDistributionPoints"); - break; - case OID_AUTHORITY_KEY_ID: - x509_parse_authorityKeyIdentifier(object, level, - &this->authKeyID, &this->authKeySerialNumber); - break; - case OID_TARGET_INFORMATION: - DBG2(" need to parse targetInformation"); - break; - case OID_NO_REV_AVAIL: - this->noRevAvail = TRUE; - break; - default: - break; - } - } - break; - case AC_OBJ_ALGORITHM: - this->algorithm = parse_algorithmIdentifier(object, level, NULL); - break; - case AC_OBJ_SIGNATURE: - this->signature = object; - break; - default: - break; - } - objectID++; - } - this->installed = time(NULL); - return TRUE; -} - -/** - * Implementation of x509ac_t.list. - */ -static void list(const private_x509ac_t *this, FILE *out, bool utc) -{ - time_t now = time(NULL); - - fprintf(out, "%#T\n", &this->installed, utc); - - if (this->entityName) - { - fprintf(out, " holder: '%D'\n", this->entityName); - } - if (this->holderIssuer) - { - fprintf(out, " hissuer: '%D'\n", this->holderIssuer); - } - if (this->holderSerial.ptr) - { - fprintf(out, " hserial: %#B\n", &this->holderSerial); - } - - /* list all group attributes on a single line */ - fprintf(out, " groups: "); - ietfAttr_list_list(this->groups, out); - fprintf(out, "\n"); - - fprintf(out, " issuer: '%D'\n", this->issuerName); - fprintf(out, " serial: %#B\n", &this->serialNumber); - - fprintf(out, " validity: not before %#T, ", &this->notBefore, utc); - if (now < this->notBefore) - { - fprintf(out, "not valid yet (valid in %#V)\n", &now, &this->notBefore); - } - else - { - fprintf(out, "ok\n"); - } - - fprintf(out, " not after %#T, ", &this->notAfter, utc); - if (now > this->notAfter) - { - fprintf(out, "expired (%#V ago)\n", &now, &this->notAfter); - } - else - { - fprintf(out, "ok"); - if (now > this->notAfter - ACERT_WARNING_INTERVAL * 60 * 60 * 24) - { - fprintf(out, " (expires in %#V)", &now, &this->notAfter); - } - fprintf(out, " \n"); - } - - if (this->authKeyID.ptr) - { - fprintf(out, " authkey: %#B\n", &this->authKeyID); - } - if (this->authKeySerialNumber.ptr) - { - fprintf(out, " aserial: %#B\n", &this->authKeySerialNumber); - } -} - -/** - * Implements x509ac_t.destroy - */ -static void destroy(private_x509ac_t *this) -{ - DESTROY_IF(this->holderIssuer); - DESTROY_IF(this->entityName); - DESTROY_IF(this->issuerName); - ietfAttr_list_destroy(this->charging); - ietfAttr_list_destroy(this->groups); - free(this->certificate.ptr); - free(this); -} - -/** - * Described in header. - */ -x509ac_t *x509ac_create_from_chunk(chunk_t chunk) -{ - private_x509ac_t *this = malloc_thing(private_x509ac_t); - - /* initialize */ - this->holderIssuer = NULL; - this->entityName = NULL; - this->issuerName = NULL; - this->charging = linked_list_create(); - this->groups = linked_list_create(); - - /* public functions */ - this->public.is_valid = (err_t (*) (const x509ac_t*,time_t*))is_valid; - this->public.is_newer = (bool (*) (const x509ac_t*,const x509ac_t*))is_newer; - this->public.equals_holder = (bool (*) (const x509ac_t*,const x509ac_t*))equals_holder; - this->public.list = (void (*) (const x509ac_t*,FILE*,bool))list; - this->public.destroy = (void (*) (x509ac_t*))destroy; - - if (!parse_certificate(chunk, this)) - { - destroy(this); - return NULL; - } - return &this->public; -} - -/** - * Described in header. - */ -x509ac_t *x509ac_create_from_file(const char *filename) -{ - bool pgp = FALSE; - chunk_t chunk = chunk_empty; - - if (!pem_asn1_load_file(filename, NULL, "attribute certificate", &chunk, &pgp)) - { - return NULL; - } - return x509ac_create_from_chunk(chunk); -} - diff --git a/src/libstrongswan/crypto/ac.h b/src/libstrongswan/crypto/ac.h deleted file mode 100644 index 8a4ccbd4c..000000000 --- a/src/libstrongswan/crypto/ac.h +++ /dev/null @@ -1,110 +0,0 @@ -/** - * @file ac.h - * - * @brief Interface of x509ac_t. - * - */ - -/* - * Copyright (C) 2002 Ueli Galizzi, Ariane Seiler - * Copyright (C) 2003 Martin Berner, Lukas Suter - * Copyright (C) 2007 Andreas Steffen - * - * Hochschule fuer Technik Rapperswil - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * RCSID $Id: ac.h 3300 2007-10-12 21:53:18Z andreas $ - */ - -#ifndef AC_H_ -#define AC_H_ - -#include <library.h> - -typedef struct x509ac_t x509ac_t; - -/** - * @brief X.509 attribute certificate. - * - * @b Constructors: - * - x509ac_create_from_chunk() - * - x509ac_create_from_file() - * - * @ingroup crypto - */ -struct x509ac_t { - - /** - * @brief Checks the validity interval of the attribute certificate - * - * @param this certificate being examined - * @param until until = min(until, notAfter) - * @return NULL if the certificate is valid - */ - err_t (*is_valid) (const x509ac_t *this, time_t *until); - - /** @brief Checks if this attr cert is newer than the other attr cert - * - * @param this calling object - * @param other other attr cert object - * @return TRUE if this was issued more recently than other - */ - bool (*is_newer) (const x509ac_t *this, const x509ac_t *other); - - /** - * @brief Checks if two attribute certificates belong to the same holder - * - * @param this calling attribute certificate - * @param that other attribute certificate - * @return TRUE if same holder - */ - bool (*equals_holder) (const x509ac_t *this, const x509ac_t *other); - - /** - * @brief Log the attribute certificate info to out. - * - * @param this calling object - * @param out stream to write to - * @param utc TRUE for UTC times, FALSE for local time - */ - void (*list)(const x509ac_t *this, FILE *out, bool utc); - - /** - * @brief Destroys the attribute certificate. - * - * @param this certificate to destroy - */ - void (*destroy) (x509ac_t *this); -}; - -/** - * @brief Read a x509 attribute certificate from a DER encoded blob. - * - * @param chunk chunk containing DER encoded data - * @return created x509ac_t certificate, or NULL if invalid. - * - * @ingroup crypto - */ -x509ac_t *x509ac_create_from_chunk(chunk_t chunk); - -/** - * @brief Read a x509 attribute certificate from a DER encoded file. - * - * @param filename file containing DER encoded data - * @return created x509ac_t certificate, or NULL if invalid. - * - * @ingroup crypto - */ -x509ac_t *x509ac_create_from_file(const char *filename); - -#endif /* AC_H_ */ - diff --git a/src/libstrongswan/crypto/ca.c b/src/libstrongswan/crypto/ca.c deleted file mode 100644 index 510e3528e..000000000 --- a/src/libstrongswan/crypto/ca.c +++ /dev/null @@ -1,813 +0,0 @@ -/** - * @file ca.c - * - * @brief Implementation of ca_info_t. - * - */ - -/* - * Copyright (C) 2007 Andreas Steffen - * Hochschule fuer Technik Rapperswil - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -#include <sys/stat.h> -#include <unistd.h> -#include <string.h> -#include <stdio.h> -#include <pthread.h> - -#include "x509.h" -#include "crl.h" -#include "ca.h" -#include "ac.h" -#include "certinfo.h" -#include "ocsp.h" - -#include <library.h> -#include <debug.h> -#include <utils/linked_list.h> -#include <utils/identification.h> -#include <utils/fetcher.h> - -typedef struct private_ca_info_t private_ca_info_t; - -/** - * Private data of a ca_info_t object. - */ -struct private_ca_info_t { - /** - * Public interface for this ca info record - */ - ca_info_t public; - - /** - * Name of the ca info record - */ - char *name; - - /** - * Time when ca info record was installed - */ - time_t installed; - - /** - * Distinguished Name of the CA - */ - x509_t *cacert; - - /** - * List of attribute certificates - */ - linked_list_t *attrcerts; - - /** - * List of crl URIs - */ - linked_list_t *crluris; - - /** - * List of ocsp URIs - */ - linked_list_t *ocspuris; - - /** - * CRL issued by this ca - */ - crl_t *crl; - - /** - * List of certificate info records - */ - linked_list_t *certinfos; - - /** - * mutex controls access to the elements: - * name, crluris, ocspuris, crl, and certinfos - */ - pthread_mutex_t mutex; -}; - -/** - * static options set by ca_info_set_options() - */ -static strict_t strict_crl_policy = STRICT_NO; -static bool cache_crls = FALSE; -static u_int crl_check_interval = 0; - -/** - * Implements ca_info_t.equals - */ -static bool equals(const private_ca_info_t *this, const private_ca_info_t *that) -{ - return chunk_equals(this->cacert->get_keyid(this->cacert), - that->cacert->get_keyid(that->cacert)); -} - -/** - * Implements ca_info_t.equals_name_release_info - */ -static bool equals_name_release_info(private_ca_info_t *this, const char *name) -{ - bool found; - - pthread_mutex_lock(&(this->mutex)); - found = this->name != NULL && streq(this->name, name); - - if (found) - { - this->crluris->destroy_offset(this->crluris, - offsetof(identification_t, destroy)); - this->crluris = linked_list_create(); - - this->ocspuris->destroy_offset(this->ocspuris, - offsetof(identification_t, destroy)); - this->ocspuris = linked_list_create(); - - free(this->name); - this->name = NULL; - } - - pthread_mutex_unlock(&(this->mutex)); - return found; -} - -/** - * Implements ca_info_t.is_crl_issuer - */ -static bool is_cert_issuer(private_ca_info_t *this, const x509_t *cert) -{ - return cert->is_issuer(cert, this->cacert); -} - -/** - * Implements ca_info_t.is_crl_issuer - */ -static bool is_crl_issuer(private_ca_info_t *this, const crl_t *crl) -{ - return crl->is_issuer(crl, this->cacert); -} - -/** - * Implements ca_info_t.is_ca - */ -static bool is_ca(private_ca_info_t *this) -{ - return this->cacert->is_ca(this->cacert); -} - -/** - * Implements ca_info_t.is_strict - */ -static bool is_strict(private_ca_info_t *this) -{ - bool strict = strict_crl_policy != STRICT_NO; - - if (strict_crl_policy == STRICT_IFURI) - { - pthread_mutex_lock(&(this->mutex)); - strict = this->crluris->get_count(this->crluris) > 0 || - this->ocspuris->get_count(this->ocspuris) > 0; - pthread_mutex_unlock(&(this->mutex)); - } - return strict; -} - -/** - * Implements ca_info_t.has_crl - */ -static bool has_crl(private_ca_info_t *this) -{ - bool found; - - pthread_mutex_lock(&(this->mutex)); - found = this->crl != NULL; - pthread_mutex_unlock(&(this->mutex)); - - return found; -} - -/** - * Implements ca_info_t.has_certinfos - */ -static bool has_certinfos(private_ca_info_t *this) -{ - bool found; - - pthread_mutex_lock(&(this->mutex)); - found = this->certinfos->get_count(this->certinfos) > 0; - pthread_mutex_unlock(&(this->mutex)); - - return found; -} - -/** - * Implements ca_info_t.add_crl - */ -static void add_crl(private_ca_info_t *this, crl_t *crl) -{ - pthread_mutex_lock(&(this->mutex)); - - if (this->crl) - { - if (crl->is_newer(crl, this->crl)) - { - this->crl->destroy(this->crl); - this->crl = crl; - DBG1(" this crl is newer - existing crl replaced"); - } - else - { - crl->destroy(crl); - DBG1(" this crl is not newer - existing crl retained"); - } - } - else - { - this->crl = crl; - DBG2(" crl added"); - } - - pthread_mutex_unlock(&(this->mutex)); -} - -/** - * Implements ca_info_t.list_crl - */ -static void list_crl(private_ca_info_t *this, FILE *out, bool utc) -{ - pthread_mutex_lock(&this->mutex); - this->crl->list(this->crl, out, utc); - pthread_mutex_unlock(&this->mutex); -} - -/** - * Implements ca_info_t.list_certinfos - */ -static void list_certinfos(private_ca_info_t *this, FILE *out, bool utc) -{ - iterator_t *iterator; - certinfo_t *certinfo; - chunk_t authkey; - - pthread_mutex_lock(&this->mutex); - - authkey = this->cacert->get_subjectKeyID(this->cacert); - fprintf(out," authname: '%D'\n", this->cacert->get_subject(this->cacert)); - fprintf(out," authkey: %#B\n", &authkey); - - iterator = this->certinfos->create_iterator(this->certinfos, TRUE); - while (iterator->iterate(iterator, (void**)&certinfo)) - { - time_t nextUpdate, thisUpdate, now; - chunk_t serial; - - now = time(NULL); - nextUpdate = certinfo->get_nextUpdate(certinfo); - thisUpdate = certinfo->get_thisUpdate(certinfo); - serial = certinfo->get_serialNumber(certinfo); - - fprintf(out, "%#T, until %#T, ", &thisUpdate, utc, &nextUpdate, utc); - if (now > nextUpdate) - { - fprintf(out, "expired (%#V ago)\n", &now, &nextUpdate); - } - else - { - fprintf(out, "ok (expires in %#V)\n", &now, &nextUpdate); - } - fprintf(out, " serial: %#B, %N\n", &serial, - cert_status_names, certinfo->get_status(certinfo)); - } - iterator->destroy(iterator); - - pthread_mutex_unlock(&this->mutex); -} - -/** - * Find an exact copy of an identification in a linked list - */ -static identification_t* find_identification(linked_list_t *list, identification_t *id) -{ - identification_t *found_id = NULL, *current_id; - - iterator_t *iterator = list->create_iterator(list, TRUE); - - while (iterator->iterate(iterator, (void**)¤t_id)) - { - if (id->equals(id, current_id)) - { - found_id = current_id; - break; - } - } - iterator->destroy(iterator); - - return found_id; -} - -/** - * Add a unique identification to a linked list - */ -static identification_t *add_identification(linked_list_t *list, identification_t *id) -{ - identification_t *found_id = find_identification(list, id); - - if (found_id) - { - id->destroy(id); - return found_id; - } - else - { - list->insert_last(list, (void*)id); - return id; - } -} - -/** - * Implements ca_info_t.add_crluri - */ -static void add_crluri(private_ca_info_t *this, chunk_t uri) -{ - if (uri.len < 6 || - (strncasecmp(uri.ptr, "http", 4) != 0 && - strncasecmp(uri.ptr, "ldap", 4) != 0 && - strncasecmp(uri.ptr, "file", 4) != 0 && - strncasecmp(uri.ptr, "ftp", 3) != 0)) - { - DBG1(" invalid crl uri '%.*s'", uri.len, uri.ptr); - return; - } - else - { - identification_t *crluri = identification_create_from_encoding(ID_DER_ASN1_GN_URI, uri); - - pthread_mutex_lock(&(this->mutex)); - add_identification(this->crluris, crluri); - pthread_mutex_unlock(&(this->mutex)); - } -} - -/** - * Implements ca_info_t.add_ocspuri - */ -static void add_ocspuri(private_ca_info_t *this, chunk_t uri) -{ - if (uri.len < 7 || strncasecmp(uri.ptr, "http", 4) != 0) - { - DBG1(" invalid ocsp uri '%.*s'", uri.len, uri.ptr); - return; - } - else - { - identification_t *ocspuri = identification_create_from_encoding(ID_DER_ASN1_GN_URI, uri); - - pthread_mutex_lock(&(this->mutex)); - add_identification(this->ocspuris, ocspuri); - pthread_mutex_unlock(&(this->mutex)); - } -} - -/** - * Implements ca_info_t.add_info. - */ -void add_info (private_ca_info_t *this, const private_ca_info_t *that) -{ - pthread_mutex_lock(&(this->mutex)); - - if (this->name == NULL && that->name != NULL) - { - this->name = strdup(that->name); - } - - pthread_mutex_unlock(&(this->mutex)); - - { - identification_t *uri; - - iterator_t *iterator = that->crluris->create_iterator(that->crluris, TRUE); - - while (iterator->iterate(iterator, (void**)&uri)) - { - if (uri->get_type(uri) == ID_DER_ASN1_GN_URI) - { - add_crluri(this, uri->get_encoding(uri)); - } - } - iterator->destroy(iterator); - } - - { - identification_t *uri; - - iterator_t *iterator = that->ocspuris->create_iterator(that->ocspuris, TRUE); - - while (iterator->iterate(iterator, (void**)&uri)) - { - if (uri->get_type(uri) == ID_DER_ASN1_GN_URI) - { - add_ocspuri(this, uri->get_encoding(uri)); - } - } - iterator->destroy(iterator); - } -} - -/** - * Implements ca_info_t.get_certificate. - */ -static x509_t* get_certificate(private_ca_info_t* this) -{ - return this->cacert; -} - -/** - * caches a crl by saving it to a given crl directory - */ -void cache_crl(private_ca_info_t* this, const char *crl_dir, crl_t *crl) -{ - char buffer[BUF_LEN]; - char *path; - char *pos = buffer; - int len = BUF_LEN; - int n; - - chunk_t authKeyID = this->cacert->get_subjectKeyID(this->cacert); - chunk_t uri; - - uri.ptr = buffer; - uri.len = 7 + strlen(crl_dir) + 1 + 2*authKeyID.len + 4; - - if (uri.len >= BUF_LEN) - { - DBG1("file uri exceeds buffer length of %d bytes - crl not saved", BUF_LEN); - return; - } - - /* print the file uri prefix */ - n = snprintf(pos, len, "file://"); - pos += n; len -= n; - - /* remember the start of the path string */ - path = pos; - - /* print the default crl directory path */ - n = snprintf(pos, len, "%s/", crl_dir); - pos += n; len -= n; - - /* create and print a unique crl filename derived from the authKeyID */ - while (authKeyID.len-- > 0) - { - n = snprintf(pos, len, "%02x", *authKeyID.ptr++); - pos += n; len -= n; - } - - /* add the file suffix */ - n = snprintf(pos, len, ".crl"); - - if (crl->write_to_file(crl, path, 0022, TRUE)) - { - identification_t *crluri = identification_create_from_encoding(ID_DER_ASN1_GN_URI, uri); - - add_identification(this->crluris, crluri); - } -} - -/** - * Implements ca_info_t.verify_by_crl. - */ -static cert_status_t verify_by_crl(private_ca_info_t* this, certinfo_t *certinfo, - const char *crl_dir) -{ - rsa_public_key_t *issuer_public_key = this->cacert->get_public_key(this->cacert); - bool stale; - - pthread_mutex_lock(&(this->mutex)); - if (this->crl == NULL) - { - stale = TRUE; - DBG1("no crl is locally available"); - } - else - { - stale = !this->crl->is_valid(this->crl); - DBG1("crl is %s", stale? "stale":"valid"); - } - - if (stale && crl_check_interval > 0) - { - iterator_t *iterator = this->crluris->create_iterator(this->crluris, TRUE); - identification_t *uri; - - while (iterator->iterate(iterator, (void**)&uri)) - { - fetcher_t *fetcher; - char uri_string[BUF_LEN]; - chunk_t uri_chunk = uri->get_encoding(uri); - chunk_t response_chunk; - - snprintf(uri_string, BUF_LEN, "%.*s", uri_chunk.len, uri_chunk.ptr); - fetcher = fetcher_create(uri_string); - - response_chunk = fetcher->get(fetcher); - fetcher->destroy(fetcher); - if (response_chunk.ptr != NULL) - { - crl_t *crl = crl_create_from_chunk(response_chunk); - - if (crl == NULL) - { - free(response_chunk.ptr); - continue; - } - if (!is_crl_issuer(this, crl)) - { - DBG1(" fetched crl has wrong issuer"); - crl->destroy(crl); - continue; - } - if (!crl->verify(crl, issuer_public_key)) - { - DBG1("fetched crl signature is invalid"); - crl->destroy(crl); - continue; - } - DBG2("fetched crl signature is valid"); - - if (this->crl == NULL) - { - this->crl = crl; - } - else if (crl->is_newer(crl, this->crl)) - { - this->crl->destroy(this->crl); - this->crl = crl; - DBG1("this crl is newer - existing crl replaced"); - } - else - { - crl->destroy(crl); - DBG1("this crl is not newer - existing crl retained"); - continue; - } - if (crl->is_valid(crl)) - { - if (cache_crls && strncasecmp(uri_string, "file", 4) != 0) - { - cache_crl(this, crl_dir, crl); - } - /* we found a valid crl and therefore exit the fetch loop */ - break; - } - else - { - DBG1("fetched crl is stale"); - } - } - } - iterator->destroy(iterator); - } - - if (this->crl) - { - if (!this->crl->verify(this->crl, issuer_public_key)) - { - DBG1("crl signature is invalid"); - goto ret; - } - DBG2("crl signature is valid"); - - this->crl->get_status(this->crl, certinfo); - } - -ret: - pthread_mutex_unlock(&(this->mutex)); - return certinfo->get_status(certinfo); -} - -/** - * Implements ca_info_t.verify_by_ocsp. - */ -static cert_status_t verify_by_ocsp(private_ca_info_t* this, - certinfo_t *certinfo, - credential_store_t *credentials) -{ - bool stale; - iterator_t *iterator; - certinfo_t *cached_certinfo = NULL; - int comparison = 1; - - pthread_mutex_lock(&(this->mutex)); - - /* do we support OCSP at all? */ - if (this->ocspuris->get_count(this->ocspuris) == 0) - { - goto ret; - } - - iterator = this->certinfos->create_iterator(this->certinfos, TRUE); - - /* find the list insertion point in alphabetical order */ - while(iterator->iterate(iterator, (void**)&cached_certinfo)) - { - comparison = certinfo->compare_serialNumber(certinfo, cached_certinfo); - - if (comparison <= 0) - { - break; - } - } - - /* do we have a valid certinfo_t for this serial number in our cache? */ - if (comparison == 0) - { - stale = cached_certinfo->get_nextUpdate(cached_certinfo) < time(NULL); - DBG1("ocsp status in cache is %s", stale ? "stale":"fresh"); - } - else - { - stale = TRUE; - DBG1("ocsp status is not in cache"); - } - - if (stale) - { - ocsp_t *ocsp; - - ocsp = ocsp_create(this->cacert, this->ocspuris); - ocsp->fetch(ocsp, certinfo, credentials); - if (certinfo->get_status(certinfo) != CERT_UNDEFINED) - { - if (comparison != 0) - { - cached_certinfo = certinfo_create(certinfo->get_serialNumber(certinfo)); - - if (comparison > 0) - { - this->certinfos->insert_last(this->certinfos, (void *)cached_certinfo); - } - else - { - iterator->insert_before(iterator, (void *)cached_certinfo); - } - } - cached_certinfo->update(cached_certinfo, certinfo); - } - ocsp->destroy(ocsp); - } - else - { - certinfo->update(certinfo, cached_certinfo); - } - - iterator->destroy(iterator); - -ret: - pthread_mutex_unlock(&(this->mutex)); - return certinfo->get_status(certinfo); -} - -/** - * Implements ca_info_t.purge_ocsp - */ -static void purge_ocsp(private_ca_info_t *this) -{ - pthread_mutex_lock(&(this->mutex)); - - this->certinfos->destroy_offset(this->certinfos, - offsetof(certinfo_t, destroy)); - this->certinfos = linked_list_create(); - - pthread_mutex_unlock(&(this->mutex)); -} - -/** - * Implements ca_info_t.destroy - */ -static void destroy(private_ca_info_t *this) -{ - this->attrcerts->destroy_offset(this->attrcerts, - offsetof(x509ac_t, destroy)); - this->crluris->destroy_offset(this->crluris, - offsetof(identification_t, destroy)); - this->ocspuris->destroy_offset(this->ocspuris, - offsetof(identification_t, destroy)); - this->certinfos->destroy_offset(this->certinfos, - offsetof(certinfo_t, destroy)); - DESTROY_IF(this->crl); - free(this->name); - free(this); -} - -/** - * list the info of this CA - */ -static void list(private_ca_info_t* this, FILE* out, bool utc) -{ - chunk_t chunk; - identification_t *uri; - iterator_t *iterator; - bool first; - - pthread_mutex_lock(&(this->mutex)); - fprintf(out, "%#T", &this->installed, utc); - - if (this->name) - { - fprintf(out, ", \"%s\"\n", this->name); - } - else - { - fprintf(out, "\n"); - } - - fprintf(out, " authname: '%D'\n", this->cacert->get_subject(this->cacert)); - chunk = this->cacert->get_subjectKeyID(this->cacert); - fprintf(out, " authkey: %#B\n", &chunk); - chunk = this->cacert->get_keyid(this->cacert); - fprintf(out, " keyid: %#B\n", &chunk); - - first = TRUE; - iterator = this->crluris->create_iterator(this->crluris, TRUE); - while (iterator->iterate(iterator, (void**)&uri)) - { - fprintf(out, " %s '%D'\n", first ? "crluris:":" ", uri); - first = FALSE; - } - iterator->destroy(iterator); - - first = TRUE; - iterator = this->ocspuris->create_iterator(this->ocspuris, TRUE); - while (iterator->iterate(iterator, (void**)&uri)) - { - fprintf(out, " %s '%D'\n", first ? "ocspuris:":" ", uri); - first = FALSE; - } - iterator->destroy(iterator); - pthread_mutex_unlock(&(this->mutex)); -} - -/* - * Described in header. - */ -void ca_info_set_options(strict_t strict, bool cache, u_int interval) -{ - strict_crl_policy = strict; - cache_crls = cache; - crl_check_interval = interval; -} - -/* - * Described in header. - */ -ca_info_t *ca_info_create(const char *name, x509_t *cacert) -{ - private_ca_info_t *this = malloc_thing(private_ca_info_t); - - /* initialize */ - this->installed = time(NULL); - this->name = (name == NULL)? NULL:strdup(name); - this->cacert = cacert; - this->attrcerts = linked_list_create(); - this->crluris = linked_list_create(); - this->ocspuris = linked_list_create(); - this->certinfos = linked_list_create(); - this->crl = NULL; - - /* initialize the mutex */ - pthread_mutex_init(&(this->mutex), NULL); - - /* public functions */ - this->public.equals = (bool (*) (const ca_info_t*,const ca_info_t*))equals; - this->public.equals_name_release_info = (bool (*) (ca_info_t*,const char*))equals_name_release_info; - this->public.is_cert_issuer = (bool (*) (ca_info_t*,const x509_t*))is_cert_issuer; - this->public.is_crl_issuer = (bool (*) (ca_info_t*,const crl_t*))is_crl_issuer; - this->public.is_ca = (bool (*) (ca_info_t*))is_ca; - this->public.is_strict = (bool (*) (ca_info_t*))is_strict; - this->public.add_info = (void (*) (ca_info_t*,const ca_info_t*))add_info; - this->public.add_crl = (void (*) (ca_info_t*,crl_t*))add_crl; - this->public.has_crl = (bool (*) (ca_info_t*))has_crl; - this->public.has_certinfos = (bool (*) (ca_info_t*))has_certinfos; - this->public.list = (void (*) (ca_info_t*,FILE*,bool))list; - this->public.list_crl = (void (*) (ca_info_t*,FILE*,bool))list_crl; - this->public.list_certinfos = (void (*) (ca_info_t*,FILE*,bool))list_certinfos; - this->public.add_crluri = (void (*) (ca_info_t*,chunk_t))add_crluri; - this->public.add_ocspuri = (void (*) (ca_info_t*,chunk_t))add_ocspuri; - this->public.get_certificate = (x509_t* (*) (ca_info_t*))get_certificate; - this->public.verify_by_crl = (cert_status_t (*) (ca_info_t*,certinfo_t*, const char*))verify_by_crl; - this->public.verify_by_ocsp = (cert_status_t (*) (ca_info_t*,certinfo_t*,credential_store_t*))verify_by_ocsp; - this->public.purge_ocsp = (void (*) (ca_info_t*))purge_ocsp; - this->public.destroy = (void (*) (ca_info_t*))destroy; - - return &this->public; -} diff --git a/src/libstrongswan/crypto/ca.h b/src/libstrongswan/crypto/ca.h deleted file mode 100644 index ff6271b15..000000000 --- a/src/libstrongswan/crypto/ca.h +++ /dev/null @@ -1,243 +0,0 @@ -/** - * @file ca.h - * - * @brief Interface of ca_info_t. - * - */ - -/* - * Copyright (C) 2007 Andreas Steffen - * Hochschule fuer Technik Rapperswil - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -#ifndef CA_H_ -#define CA_H_ - -typedef struct ca_info_t ca_info_t; - -#include <library.h> - -#include "x509.h" -#include "crl.h" - -#define MAX_CA_PATH_LEN 7 - -/*forward declaration */ -struct credential_store_t; - -/** - * @brief X.509 certification authority information record - * - * @b Constructors: - * - ca_info_create() - * - * @ingroup transforms - */ -struct ca_info_t { - - /** - * @brief Compare two ca info records - * - * Comparison is done via the keyid of the ca certificate - * - * @param this first ca info object - * @param that second ca info objct - * @return TRUE if a match is found - */ - bool (*equals) (const ca_info_t *this, const ca_info_t* that); - - /** - * @brief If the ca info record has the same name then release the name and URIs - * - * @param this ca info object - * @return TRUE if a match is found - */ - bool (*equals_name_release_info) (ca_info_t *this, const char *name); - - /** - * @brief Checks if a certificate was issued by this ca - * - * @param this ca info object - * @param cert certificate to be checked - * @return TRUE if the issuing ca has been found - */ - bool (*is_cert_issuer) (ca_info_t *this, const x509_t *cert); - - /** - * @brief Checks if a crl was issued by this ca - * - * @param this ca info object - * @param crl crl to be checked - * @return TRUE if the issuing ca has been found - */ - bool (*is_crl_issuer) (ca_info_t *this, const crl_t *crl); - - /** - * @brief Checks if the ca certificate has the isCA flag set - * - * @param this ca info object - * @return TRUE if the isCA flag is set - */ - bool (*is_ca) (ca_info_t *this); - - /** - * @brief Checks if the ca enforces a strict crl policy - * - * @param this ca info object - * @return TRUE if the crl policy is strict - */ - bool (*is_strict) (ca_info_t *this); - - /** - * @brief Merges info from a secondary ca info object - * - * @param this primary ca info object - * @param that secondary ca info object - */ - void (*add_info) (ca_info_t *this, const ca_info_t *that); - - /** - * @brief Adds a new or replaces an obsoleted CRL - * - * @param this ca info object - * @param crl crl to be added - */ - void (*add_crl) (ca_info_t *this, crl_t *crl); - - /** - * @brief Does the CA have a CRL? - * - * @param this ca info object - * @return TRUE if crl is available - */ - bool (*has_crl) (ca_info_t *this); - - /** - * @brief Does the CA have OCSP certinfos? - * - * @param this ca info object - * @return TRUE if there are any certinfos - */ - bool (*has_certinfos) (ca_info_t *this); - - /** - * @brief Print the CA info onto the console - * - * @param this ca info object - * @param out output stream - * @param utc TRUE - utc - FALSE - local time - */ - void (*list) (ca_info_t *this, FILE *out, bool utc); - - /** - * @brief List the CRL onto the console - * - * @param this ca info object - * @param out output stream - * @param utc TRUE - utc - FALSE - local time - */ - void (*list_crl) (ca_info_t *this, FILE *out, bool utc); - - /** - * @brief List the OCSP certinfos onto the console - * - * @param this ca info object - * @param out output stream - * @param utc TRUE - utc - FALSE - local time - */ - void (*list_certinfos) (ca_info_t *this, FILE *out, bool utc); - - /** - * @brief Adds a CRL URI to a list - * - * @param this ca info object - * @param uri crl uri to be added - */ - void (*add_crluri) (ca_info_t *this, chunk_t uri); - - /** - * @brief Adds a OCSP URI to a list - * - * @param this ca info object - * @param uri ocsp uri to be added - */ - void (*add_ocspuri) (ca_info_t *this, chunk_t uri); - - /** - * @brief Get the ca certificate - * - * @param this ca info object - * @return ca certificate - */ - x509_t* (*get_certificate) (ca_info_t *this); - - /** - * @brief Verify the status of a certificate by CRL - * - * @param this ca info object - * @param certinfo detailed certificate status information - * @param crl_dir directory where fetched crls should be stored - * @return certificate status - */ - cert_status_t (*verify_by_crl) (ca_info_t *this, certinfo_t *certinfo, const char *crl_dir); - - /** - * @brief Verify the status of a certificate by OCSP - * - * @param this ca info object - * @param certinfo detailed certificate status information - * @param credentials credential store needed for trust path verification - * @return certificate status - */ - cert_status_t (*verify_by_ocsp) (ca_info_t* this, certinfo_t* certinfo, struct credential_store_t* credentials); - - /** - * @brief Purge the OCSP certinfos of a ca info record - * - * @param this ca info object - */ - void (*purge_ocsp) (ca_info_t *this); - - /** - * @brief Destroys a ca info record - * - * @param this ca info to destroy - */ - void (*destroy) (ca_info_t *this); -}; - -/** - * @brief Set ca info options - * - * @param cache TRUE if crls shall be cached by storing them - * @param interval crl_check_interval to be set in seconds - * - * @ingroup crypto - */ -void ca_info_set_options(strict_t strict, bool cache, u_int interval); - -/** - * @brief Create a ca info record - * - * @param name name of the ca info record - * @param cacert path to the ca certificate - * @return created ca_info_t, or NULL if invalid. - * - * @ingroup crypto - */ -ca_info_t *ca_info_create(const char *name, x509_t *cacert); - -#endif /* CA_H_ */ diff --git a/src/libstrongswan/crypto/certinfo.c b/src/libstrongswan/crypto/certinfo.c deleted file mode 100644 index 8a125e247..000000000 --- a/src/libstrongswan/crypto/certinfo.c +++ /dev/null @@ -1,257 +0,0 @@ -/** - * @file certinfo.c - * - * @brief Implementation of certinfo_t. - * - */ - -/* - * Copyright (C) 2006 Andreas Steffen - * Hochschule fuer Technik Rapperswil - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -#include <time.h> -#include <stdio.h> - -#include <library.h> - -#include "certinfo.h" - -typedef struct private_certinfo_t private_certinfo_t; - -/** - * Private data of a certinfo_t object. - */ -struct private_certinfo_t { - /** - * Public interface for this certificate status information object. - */ - certinfo_t public; - - /** - * Serial number of the certificate - */ - chunk_t serialNumber; - - /** - * Certificate status - */ - cert_status_t status; - - /** - * Certificate status is for one-time use only - */ - bool once; - - /** - * Time when the certificate status info was generated - */ - time_t thisUpdate; - - /** - * Time when an updated certifcate status info will be available - */ - time_t nextUpdate; - - /** - * Time of certificate revocation - */ - time_t revocationTime; - - /** - * Reason of certificate revocation - */ - crl_reason_t revocationReason; -}; - -ENUM(cert_status_names, CERT_GOOD, CERT_UNTRUSTED, - "good", - "revoked", - "unknown", - "unknown", - "untrusted", -); - -ENUM(crl_reason_names, REASON_UNSPECIFIED, REASON_REMOVE_FROM_CRL, - "unspecified", - "key compromise", - "ca compromise", - "affiliation changed", - "superseded", - "cessation of operation", - "certificate hold", - "reason #7", - "remove from crl", -); - -/** - * Implements certinfo_t.compare_serialNumber - */ -static int compare_serialNumber(const private_certinfo_t *this, const private_certinfo_t *that) -{ - return chunk_compare(this->serialNumber, that->serialNumber); -} - -/** - * Implements certinfo_t.equals_serialNumber - */ -static bool equals_serialNumber(const private_certinfo_t *this, const private_certinfo_t *that) -{ - return chunk_equals(this->serialNumber, that->serialNumber); -} - -/** - * Implements certinfo_t.get_serialNumber - */ -static chunk_t get_serialNumber(const private_certinfo_t *this) -{ - return this->serialNumber; -} - -/** - * Implements certinfo_t.set_status - */ -static void set_status(private_certinfo_t *this, cert_status_t status) -{ - this->status = status; -} - -/** - * Implements certinfo_t.get_status - */ -static cert_status_t get_status(const private_certinfo_t *this) -{ - return this->status; -} - -/** - * Implements certinfo_t.set_thisUpdate - */ -static void set_thisUpdate(private_certinfo_t *this, time_t thisUpdate) -{ - this->thisUpdate = thisUpdate; -} - -/** - * Implements certinfo_t.get_thisUpdate - */ -static time_t get_thisUpdate(const private_certinfo_t *this) -{ - return this->thisUpdate; -} - -/** - * Implements certinfo_t.set_nextUpdate - */ -static void set_nextUpdate(private_certinfo_t *this, time_t nextUpdate) -{ - this->nextUpdate = nextUpdate; -} - -/** - * Implements certinfo_t.get_nextUpdate - */ -static time_t get_nextUpdate(const private_certinfo_t *this) -{ - return this->nextUpdate; -} - -/** - * Implements certinfo_t.set_revocationTime - */ -static void set_revocationTime(private_certinfo_t *this, time_t revocationTime) -{ - this->revocationTime = revocationTime; -} - -/** - * Implements certinfo_t.get_revocationTime - */ -static time_t get_revocationTime(const private_certinfo_t *this) -{ - return this->revocationTime; -} - -/** - * Implements certinfo_t.set_revocationReason - */ -static void set_revocationReason(private_certinfo_t *this, crl_reason_t reason) -{ - this->revocationReason = reason; -} - -/** - * Implements certinfo_t.get_revocationReason - */ -static crl_reason_t get_revocationReason(const private_certinfo_t *this) -{ - return this->revocationReason; -} - -/** - * Implements certinfo_t.update - */ -static void update(private_certinfo_t *this, const private_certinfo_t *that) -{ - if (equals_serialNumber(this, that)) - { - chunk_t this_serialNumber = this->serialNumber; - - *this = *that; - this->serialNumber = this_serialNumber; - } -} - -/** - * Implements certinfo_t.destroy - */ -static void destroy(private_certinfo_t *this) -{ - free(this->serialNumber.ptr); - free(this); -} - -/* - * Described in header. - */ -certinfo_t *certinfo_create(chunk_t serial) -{ - private_certinfo_t *this = malloc_thing(private_certinfo_t); - - /* initialize */ - this->serialNumber = chunk_clone(serial); - this->status = CERT_UNDEFINED; - this->thisUpdate = UNDEFINED_TIME; - this->nextUpdate = UNDEFINED_TIME; - this->revocationTime = UNDEFINED_TIME; - this->revocationReason = REASON_UNSPECIFIED; - - /* public functions */ - this->public.compare_serialNumber = (int (*) (const certinfo_t*,const certinfo_t*))compare_serialNumber; - this->public.equals_serialNumber = (bool (*) (const certinfo_t*,const certinfo_t*))equals_serialNumber; - this->public.get_serialNumber = (chunk_t (*) (const certinfo_t*))get_serialNumber; - this->public.set_status = (void (*) (certinfo_t*,cert_status_t))set_status; - this->public.get_status = (cert_status_t (*) (const certinfo_t*))get_status; - this->public.set_thisUpdate = (void (*) (certinfo_t*,time_t))set_thisUpdate; - this->public.get_thisUpdate = (time_t (*) (const certinfo_t*))get_thisUpdate; - this->public.set_nextUpdate = (void (*) (certinfo_t*,time_t))set_nextUpdate; - this->public.get_nextUpdate = (time_t (*) (const certinfo_t*))get_nextUpdate; - this->public.set_revocationTime = (void (*) (certinfo_t*,time_t))set_revocationTime; - this->public.get_revocationTime = (time_t (*) (const certinfo_t*))get_revocationTime; - this->public.set_revocationReason = (void (*) (certinfo_t*, crl_reason_t))set_revocationReason; - this->public.get_revocationReason = (crl_reason_t(*) (const certinfo_t*))get_revocationReason; - this->public.update = (void (*) (certinfo_t*, const certinfo_t*))update; - this->public.destroy = (void (*) (certinfo_t*))destroy; - - return &this->public; -} diff --git a/src/libstrongswan/crypto/certinfo.h b/src/libstrongswan/crypto/certinfo.h deleted file mode 100644 index 476befda8..000000000 --- a/src/libstrongswan/crypto/certinfo.h +++ /dev/null @@ -1,203 +0,0 @@ -/** - * @file certinfo.h - * - * @brief Interface of certinfo_t. - * - */ - -/* - * Copyright (C) 2006 Andreas Steffen - * Hochschule fuer Technik Rapperswil - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -#ifndef CERTINFO_H_ -#define CERTINFO_H_ - -typedef enum cert_status_t cert_status_t; -typedef enum crl_reason_t crl_reason_t; -typedef struct certinfo_t certinfo_t; - -#include <library.h> - -/** - * RFC 2560 OCSP - certificate status - */ -enum cert_status_t { - CERT_GOOD = 0, - CERT_REVOKED = 1, - CERT_UNKNOWN = 2, - CERT_UNDEFINED = 3, - CERT_UNTRUSTED = 4 /* private use */ -}; - -extern enum_name_t *cert_status_names; - -/** - * RFC 2459 CRL reason codes - */ -enum crl_reason_t { - REASON_UNSPECIFIED = 0, - REASON_KEY_COMPROMISE = 1, - REASON_CA_COMPROMISE = 2, - REASON_AFFILIATION_CHANGED = 3, - REASON_SUPERSEDED = 4, - REASON_CESSATION_OF_OPERATON = 5, - REASON_CERTIFICATE_HOLD = 6, - REASON_REMOVE_FROM_CRL = 8 -}; - -extern enum_name_t *crl_reason_names; - -/** - * @brief X.509 certificate status information - * - * @ingroup transforms - */ -struct certinfo_t { - - /** - * @brief Check if both certinfo objects have the same serialNumber. - * - * @param this calling object - * @param that second certinfo_t object - * @return TRUE if the same serialNumber - */ - bool (*equals_serialNumber) (const certinfo_t *this, const certinfo_t *that); - - /** - * @brief Compares two serial numbers. - * - * @param this calling object - * @param that second certinfo_t object - * @return negative if this is smaller than that - * zero if this equals that - * positive if this is greater than that - */ - int (*compare_serialNumber) (const certinfo_t *this, const certinfo_t *that); - - /** - * @brief Get serial number. - * - * @param this calling object - * @return serialNumber - */ - chunk_t (*get_serialNumber) (const certinfo_t *this); - - /** - * @brief Set certificate status. - * - * @param this calling object - * @param status status - */ - void (*set_status) (certinfo_t *this, cert_status_t status); - - /** - * @brief Get certificate status. - * - * @param this calling object - * @return status - */ - cert_status_t (*get_status) (const certinfo_t *this); - - /** - * @brief Set thisUpdate. - * - * @param this calling object - * @param thisUpdate thisUpdate - */ - void (*set_thisUpdate) (certinfo_t *this, time_t thisUpdate); - - /** - * @brief Get thisUpdate. - * - * @param this calling object - * @return thisUpdate - */ - time_t (*get_thisUpdate) (const certinfo_t *this); - - /** - * @brief Set nextUpdate. - * - * @param this calling object - * @param nextUpdate - */ - void (*set_nextUpdate) (certinfo_t *this, time_t nextUpdate); - - /** - * @brief Get nextUpdate. - * - * @param this calling object - * @return nextUpdate - */ - time_t (*get_nextUpdate) (const certinfo_t *this); - - /** - * @brief Set revocationTime. - * - * @param this calling object - * @param revocationTime revocationTime - */ - void (*set_revocationTime) (certinfo_t *this, time_t revocationTime); - - /** - * @brief Get revocationTime. - * - * @param this calling object - * @return revocationTime - */ - time_t (*get_revocationTime) (const certinfo_t *this); - - /** - * @brief Set revocationReason. - * - * @param this calling object - * @param reason revocationReason - */ - void (*set_revocationReason) (certinfo_t *this, crl_reason_t reason); - - /** - * @brief Get revocationReason. - * - * @param this calling object - * @return revocationReason - */ - crl_reason_t (*get_revocationReason) (const certinfo_t *this); - - /** - * @brief Set revocationReason. - * - * @param this calling object to be updated - * @param that object containing updated information - */ - void (*update) (certinfo_t *this, const certinfo_t *that); - - /** - * @brief Destroys the certinfo_t object. - * - * @param this certinfo_t to destroy - */ - void (*destroy) (certinfo_t *this); - -}; - -/** - * @brief Create a certinfo_t object. - * - * @param serial chunk serial number of the certificate - * @return created certinfo_t object - * - * @ingroup transforms - */ -certinfo_t *certinfo_create(chunk_t serial); - -#endif /* CERTINFO_H_ */ diff --git a/src/libstrongswan/crypto/crl.c b/src/libstrongswan/crypto/crl.c deleted file mode 100755 index ab23bb9ec..000000000 --- a/src/libstrongswan/crypto/crl.c +++ /dev/null @@ -1,536 +0,0 @@ -/** - * @file crl.c - * - * @brief Implementation of crl_t. - * - */ - -/* - * Copyright (C) 2006 Andreas Steffen - * Hochschule fuer Technik Rapperswil - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * RCSID $Id: crl.c 3355 2007-11-20 12:06:40Z martin $ - */ - -#include <sys/stat.h> -#include <unistd.h> -#include <string.h> -#include <stdio.h> - -#include <library.h> -#include <debug.h> -#include <asn1/oid.h> -#include <asn1/asn1.h> -#include <asn1/pem.h> -#include <utils/linked_list.h> -#include <utils/identification.h> - -#include "certinfo.h" -#include "x509.h" -#include "crl.h" - -#define CRL_WARNING_INTERVAL 7 /* days */ - -/* access structure for a revoked certificate */ - -typedef struct revokedCert_t revokedCert_t; - -struct revokedCert_t { - chunk_t userCertificate; - time_t revocationDate; - crl_reason_t revocationReason; -}; - -typedef struct private_crl_t private_crl_t; - -/** - * Private data of a crl_t object. - */ -struct private_crl_t { - /** - * Public interface for this crl. - */ - crl_t public; - - /** - * Time when crl was installed - */ - time_t installed; - - /** - * List of crlDistributionPoints - */ - linked_list_t *crlDistributionPoints; - - /** - * X.509 crl in DER format - */ - chunk_t certificateList; - - /** - * X.509 crl body over which signature is computed - */ - chunk_t tbsCertList; - - /** - * Version of the X.509 crl - */ - u_int version; - - /** - * Signature algorithm - */ - int sigAlg; - - /** - * ID representing the crl issuer - */ - identification_t *issuer; - - /** - * CRL number - */ - chunk_t crlNumber; - - /** - * Time when the crl was generated - */ - time_t thisUpdate; - - /** - * Time when an update crl will be available - */ - time_t nextUpdate; - - /** - * List of identification_t's representing subjectAltNames - */ - linked_list_t *revokedCertificates; - - /** - * Authority Key Identifier - */ - chunk_t authKeyID; - - /** - * Authority Key Serial Number - */ - chunk_t authKeySerialNumber; - - /** - * Signature algorithm (must be identical to sigAlg) - */ - int algorithm; - - /** - * Signature - */ - chunk_t signature; -}; - -/** - * ASN.1 definition of an X.509 certificate revocation list - */ -static const asn1Object_t crlObjects[] = { - { 0, "certificateList", ASN1_SEQUENCE, ASN1_OBJ }, /* 0 */ - { 1, "tbsCertList", ASN1_SEQUENCE, ASN1_OBJ }, /* 1 */ - { 2, "version", ASN1_INTEGER, ASN1_OPT | - ASN1_BODY }, /* 2 */ - { 2, "end opt", ASN1_EOC, ASN1_END }, /* 3 */ - { 2, "signature", ASN1_EOC, ASN1_RAW }, /* 4 */ - { 2, "issuer", ASN1_SEQUENCE, ASN1_OBJ }, /* 5 */ - { 2, "thisUpdate", ASN1_EOC, ASN1_RAW }, /* 6 */ - { 2, "nextUpdate", ASN1_EOC, ASN1_RAW }, /* 7 */ - { 2, "revokedCertificates", ASN1_SEQUENCE, ASN1_OPT | - ASN1_LOOP }, /* 8 */ - { 3, "certList", ASN1_SEQUENCE, ASN1_NONE }, /* 9 */ - { 4, "userCertificate", ASN1_INTEGER, ASN1_BODY }, /* 10 */ - { 4, "revocationDate", ASN1_EOC, ASN1_RAW }, /* 11 */ - { 4, "crlEntryExtensions", ASN1_SEQUENCE, ASN1_OPT | - ASN1_LOOP }, /* 12 */ - { 5, "extension", ASN1_SEQUENCE, ASN1_NONE }, /* 13 */ - { 6, "extnID", ASN1_OID, ASN1_BODY }, /* 14 */ - { 6, "critical", ASN1_BOOLEAN, ASN1_DEF | - ASN1_BODY }, /* 15 */ - { 6, "extnValue", ASN1_OCTET_STRING, ASN1_BODY }, /* 16 */ - { 4, "end opt or loop", ASN1_EOC, ASN1_END }, /* 17 */ - { 2, "end opt or loop", ASN1_EOC, ASN1_END }, /* 18 */ - { 2, "optional extensions", ASN1_CONTEXT_C_0, ASN1_OPT }, /* 19 */ - { 3, "crlExtensions", ASN1_SEQUENCE, ASN1_LOOP }, /* 20 */ - { 4, "extension", ASN1_SEQUENCE, ASN1_NONE }, /* 21 */ - { 5, "extnID", ASN1_OID, ASN1_BODY }, /* 22 */ - { 5, "critical", ASN1_BOOLEAN, ASN1_DEF | - ASN1_BODY }, /* 23 */ - { 5, "extnValue", ASN1_OCTET_STRING, ASN1_BODY }, /* 24 */ - { 3, "end loop", ASN1_EOC, ASN1_END }, /* 25 */ - { 2, "end opt", ASN1_EOC, ASN1_END }, /* 26 */ - { 1, "signatureAlgorithm", ASN1_EOC, ASN1_RAW }, /* 27 */ - { 1, "signatureValue", ASN1_BIT_STRING, ASN1_BODY } /* 28 */ - }; - -#define CRL_OBJ_CERTIFICATE_LIST 0 -#define CRL_OBJ_TBS_CERT_LIST 1 -#define CRL_OBJ_VERSION 2 -#define CRL_OBJ_SIG_ALG 4 -#define CRL_OBJ_ISSUER 5 -#define CRL_OBJ_THIS_UPDATE 6 -#define CRL_OBJ_NEXT_UPDATE 7 -#define CRL_OBJ_USER_CERTIFICATE 10 -#define CRL_OBJ_REVOCATION_DATE 11 -#define CRL_OBJ_CRL_ENTRY_EXTN_ID 14 -#define CRL_OBJ_CRL_ENTRY_CRITICAL 15 -#define CRL_OBJ_CRL_ENTRY_EXTN_VALUE 16 -#define CRL_OBJ_EXTN_ID 22 -#define CRL_OBJ_CRITICAL 23 -#define CRL_OBJ_EXTN_VALUE 24 -#define CRL_OBJ_ALGORITHM 27 -#define CRL_OBJ_SIGNATURE 28 -#define CRL_OBJ_ROOF 29 - -/** - * Parses a CRL revocation reason code - */ -static crl_reason_t parse_crl_reasonCode(chunk_t object) -{ - crl_reason_t reason = REASON_UNSPECIFIED; - - if (*object.ptr == ASN1_ENUMERATED && asn1_length(&object) == 1) - { - reason = *object.ptr; - } - DBG2(" '%N'", crl_reason_names, reason); - - return reason; -} - -/** - * Parses an X.509 Certificate Revocation List (CRL) - */ -bool parse_x509crl(chunk_t blob, u_int level0, private_crl_t *crl) -{ - asn1_ctx_t ctx; - bool critical; - chunk_t extnID; - chunk_t userCertificate = chunk_empty; - revokedCert_t *revokedCert = NULL; - chunk_t object; - u_int level; - int objectID = 0; - - asn1_init(&ctx, blob, level0, FALSE, FALSE); - - while (objectID < CRL_OBJ_ROOF) - { - if (!extract_object(crlObjects, &objectID, &object, &level, &ctx)) - return FALSE; - - /* those objects which will parsed further need the next higher level */ - level++; - - switch (objectID) - { - case CRL_OBJ_CERTIFICATE_LIST: - crl->certificateList = object; - break; - case CRL_OBJ_TBS_CERT_LIST: - crl->tbsCertList = object; - break; - case CRL_OBJ_VERSION: - crl->version = (object.len) ? (1+(u_int)*object.ptr) : 1; - DBG2(" v%d", crl->version); - break; - case CRL_OBJ_SIG_ALG: - crl->sigAlg = parse_algorithmIdentifier(object, level, NULL); - break; - case CRL_OBJ_ISSUER: - crl->issuer = identification_create_from_encoding(ID_DER_ASN1_DN, object); - DBG2(" '%D'", crl->issuer); - break; - case CRL_OBJ_THIS_UPDATE: - crl->thisUpdate = parse_time(object, level); - break; - case CRL_OBJ_NEXT_UPDATE: - crl->nextUpdate = parse_time(object, level); - break; - case CRL_OBJ_USER_CERTIFICATE: - userCertificate = object; - break; - case CRL_OBJ_REVOCATION_DATE: - revokedCert = malloc_thing(revokedCert_t); - revokedCert->userCertificate = userCertificate; - revokedCert->revocationDate = parse_time(object, level); - revokedCert->revocationReason = REASON_UNSPECIFIED; - crl->revokedCertificates->insert_last(crl->revokedCertificates, (void *)revokedCert); - break; - case CRL_OBJ_CRL_ENTRY_EXTN_ID: - case CRL_OBJ_EXTN_ID: - extnID = object; - break; - case CRL_OBJ_CRL_ENTRY_CRITICAL: - case CRL_OBJ_CRITICAL: - critical = object.len && *object.ptr; - DBG2(" %s",(critical)?"TRUE":"FALSE"); - break; - case CRL_OBJ_CRL_ENTRY_EXTN_VALUE: - case CRL_OBJ_EXTN_VALUE: - { - int extn_oid = known_oid(extnID); - - if (revokedCert && extn_oid == OID_CRL_REASON_CODE) - { - revokedCert->revocationReason = parse_crl_reasonCode(object); - } - else if (extn_oid == OID_AUTHORITY_KEY_ID) - { - x509_parse_authorityKeyIdentifier(object, level, - &crl->authKeyID, &crl->authKeySerialNumber); - } - else if (extn_oid == OID_CRL_NUMBER) - { - if (!parse_asn1_simple_object(&object, ASN1_INTEGER, level, "crlNumber")) - { - return FALSE; - } - crl->crlNumber = object; - } - } - break; - case CRL_OBJ_ALGORITHM: - crl->algorithm = parse_algorithmIdentifier(object, level, NULL); - if (crl->algorithm != crl->sigAlg) - { - DBG1(" signature algorithms do not agree"); - return FALSE; - } - break; - case CRL_OBJ_SIGNATURE: - crl->signature = object; - break; - default: - break; - } - objectID++; - } - time(&crl->installed); - return TRUE; -} - -/** - * Implements crl_t.is_valid - */ -static bool is_valid(const private_crl_t *this) -{ - time_t current_time = time(NULL); - - DBG2(" this update : %T", &this->thisUpdate); - DBG2(" current time: %T", ¤t_time); - DBG2(" next update: %T", &this->nextUpdate); - - return current_time < this->nextUpdate; -} - -/** - * Implements crl_t.get_issuer - */ -static identification_t *get_issuer(const private_crl_t *this) -{ - return this->issuer; -} - -/** - * Implements crl_t.equals_issuer - */ -static bool equals_issuer(const private_crl_t *this, const private_crl_t *other) -{ - return (this->authKeyID.ptr) - ? chunk_equals(this->authKeyID, other->authKeyID) - : (this->issuer->equals(this->issuer, other->issuer) - && chunk_equals_or_null(this->authKeySerialNumber, other->authKeySerialNumber)); -} - -/** - * Implements crl_t.is_issuer - */ -static bool is_issuer(const private_crl_t *this, const x509_t *issuer) -{ - return (this->authKeyID.ptr) - ? chunk_equals(this->authKeyID, issuer->get_subjectKeyID(issuer)) - : (this->issuer->equals(this->issuer, issuer->get_subject(issuer)) - && chunk_equals_or_null(this->authKeySerialNumber, issuer->get_serialNumber(issuer))); -} - -/** - * Implements crl_t.is_newer - */ -static bool is_newer(const private_crl_t *this, const private_crl_t *other) -{ - return (this->nextUpdate > other->nextUpdate); -} - -/** - * Implements crl_t.verify - */ -static bool verify(const private_crl_t *this, const rsa_public_key_t *signer) -{ - hash_algorithm_t algorithm = hasher_algorithm_from_oid(this->algorithm); - - if (algorithm == HASH_UNKNOWN) - { - DBG1(" unknown signature algorithm"); - return FALSE; - } - return signer->verify_emsa_pkcs1_signature(signer, algorithm, this->tbsCertList, this->signature) == SUCCESS; -} - -/** - * Implements crl_t.get_status - */ -static void get_status(const private_crl_t *this, certinfo_t *certinfo) -{ - chunk_t serialNumber = certinfo->get_serialNumber(certinfo); - iterator_t *iterator; - revokedCert_t *revokedCert; - - certinfo->set_nextUpdate(certinfo, this->nextUpdate); - certinfo->set_status(certinfo, CERT_GOOD); - - iterator = this->revokedCertificates->create_iterator(this->revokedCertificates, TRUE); - while (iterator->iterate(iterator, (void**)&revokedCert)) - { - if (chunk_equals(serialNumber, revokedCert->userCertificate)) - { - certinfo->set_status(certinfo, CERT_REVOKED); - certinfo->set_revocationTime(certinfo, revokedCert->revocationDate); - certinfo->set_revocationReason(certinfo, revokedCert->revocationReason); - break; - } - } - iterator->destroy(iterator); -} - -/** - * Implements crl_t.write_to_file. - */ -static bool write_to_file(private_crl_t *this, const char *path, mode_t mask, bool force) -{ - return chunk_write(this->certificateList, path, "crl", mask, force); -} - -/** - * Implements crl_t.destroy - */ -static void destroy(private_crl_t *this) -{ - this->revokedCertificates->destroy_function(this->revokedCertificates, free); - this->crlDistributionPoints->destroy_offset(this->crlDistributionPoints, - offsetof(identification_t, destroy)); - DESTROY_IF(this->issuer); - free(this->certificateList.ptr); - free(this); -} - -/** - * Implementation of crl_t.list. - */ -static void list(private_crl_t *this, FILE* out, bool utc) -{ - time_t now; - - now = time(NULL); - - fprintf(out, "%#T, revoked certs: %d\n", &this->installed, utc, - this->revokedCertificates->get_count(this->revokedCertificates)); - fprintf(out, " issuer: '%D'\n", this->issuer); - if (this->crlNumber.ptr) - { - fprintf(out, " crlnumber: %#B\n", &this->crlNumber); - } - fprintf(out, " updates: this %#T\n", &this->thisUpdate, utc); - fprintf(out, " next %#T ", &this->nextUpdate, utc); - if (this->nextUpdate == UNDEFINED_TIME) - { - fprintf(out, "ok (expires never)\n"); - } - else if (now > this->nextUpdate) - { - fprintf(out, "expired (%#V ago)\n", &now, &this->nextUpdate); - } - else if (now > this->nextUpdate - CRL_WARNING_INTERVAL * 60 * 60 * 24) - { - fprintf(out, "ok (expires in %#V)\n", &now, &this->nextUpdate); - } - else - { - fprintf(out, "ok\n"); - } - if (this->authKeyID.ptr) - { - fprintf(out, " authkey: %#B\n", &this->authKeyID); - } - if (this->authKeySerialNumber.ptr) - { - fprintf(out, " aserial: %#B\n", &this->authKeySerialNumber); - } -} - -/* - * Described in header. - */ -crl_t *crl_create_from_chunk(chunk_t chunk) -{ - private_crl_t *this = malloc_thing(private_crl_t); - - /* initialize */ - this->crlDistributionPoints = linked_list_create(); - this->tbsCertList = chunk_empty; - this->issuer = NULL; - this->crlNumber = chunk_empty; - this->revokedCertificates = linked_list_create(); - this->authKeyID = chunk_empty; - this->authKeySerialNumber = chunk_empty; - - /* public functions */ - this->public.get_issuer = (identification_t* (*) (const crl_t*))get_issuer; - this->public.equals_issuer = (bool (*) (const crl_t*,const crl_t*))equals_issuer; - this->public.is_issuer = (bool (*) (const crl_t*,const x509_t*))is_issuer; - this->public.is_valid = (bool (*) (const crl_t*))is_valid; - this->public.is_newer = (bool (*) (const crl_t*,const crl_t*))is_newer; - this->public.verify = (bool (*) (const crl_t*,const rsa_public_key_t*))verify; - this->public.get_status = (void (*) (const crl_t*,certinfo_t*))get_status; - this->public.write_to_file = (bool (*) (const crl_t*,const char*,mode_t,bool))write_to_file; - this->public.list = (void(*)(crl_t*, FILE* out, bool utc))list; - this->public.destroy = (void (*) (crl_t*))destroy; - - if (!parse_x509crl(chunk, 0, this)) - { - destroy(this); - return NULL; - } - - return &this->public; -} - -/* - * Described in header. - */ -crl_t *crl_create_from_file(const char *filename) -{ - bool pgp = FALSE; - chunk_t chunk = chunk_empty; - - if (!pem_asn1_load_file(filename, NULL, "crl", &chunk, &pgp)) - { - return NULL; - } - return crl_create_from_chunk(chunk); -} diff --git a/src/libstrongswan/crypto/crl.h b/src/libstrongswan/crypto/crl.h deleted file mode 100755 index bcf031dd4..000000000 --- a/src/libstrongswan/crypto/crl.h +++ /dev/null @@ -1,158 +0,0 @@ -/** - * @file crl.h - * - * @brief Interface of crl_t. - * - */ - -/* - * Copyright (C) 2006 Andreas Steffen - * Hochschule fuer Technik Rapperswil - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * RCSID $Id: crl.h 3300 2007-10-12 21:53:18Z andreas $ - */ - -#ifndef CRL_H_ -#define CRL_H_ - -typedef struct crl_t crl_t; - -#include <library.h> -#include <crypto/rsa/rsa_public_key.h> -#include <crypto/certinfo.h> -#include <utils/identification.h> -#include <utils/iterator.h> - -/** - * @brief X.509 certificate revocation list - * - * @b Constructors: - * - crl_create_from_chunk() - * - crl_create_from_file() - * - * @ingroup transforms - */ -struct crl_t { - - /** - * @brief Get the crl's issuer ID. - * - * The resulting ID is always a identification_t - * of type ID_DER_ASN1_DN. - * - * @param this calling object - * @return issuers ID - */ - identification_t *(*get_issuer) (const crl_t *this); - - /** - * @brief Check if both crls have the same issuer. - * - * @param this calling object - * @param other other crl - * @return TRUE if the same issuer - */ - bool (*equals_issuer) (const crl_t *this, const crl_t *other); - - /** - * @brief Check if ia candidate cert is the issuer of the crl - * - * @param this calling object - * @param issuer candidate issuer of the crl - * @return TRUE if issuer - */ - bool (*is_issuer) (const crl_t *this, const x509_t *issuer); - - /** - * @brief Checks the validity interval of the crl - * - * @param this calling object - * @return TRUE if the crl is valid - */ - bool (*is_valid) (const crl_t *this); - - /** - * @brief Checks if this crl is newer (thisUpdate) than the other crl - * - * @param this calling object - * @param other other crl object - * @return TRUE if this was issued more recently than other - */ - bool (*is_newer) (const crl_t *this, const crl_t *other); - - /** - * @brief Check if a crl is trustworthy. - * - * @param this calling object - * @param signer signer's RSA public key - * @return TRUE if crl is trustworthy - */ - bool (*verify) (const crl_t *this, const rsa_public_key_t *signer); - - /** - * @brief Get the certificate status - * - * @param this calling object - * @param certinfo certinfo is updated - */ - void (*get_status) (const crl_t *this, certinfo_t *certinfo); - - /** - * @brief Log the info of this CRL to out. - * - * @param this calling object - * @param out stream to write to - * @param utc TRUE for UTC, FALSE for local time - */ - void (*list)(crl_t *this, FILE* out, bool utc); - - /** - * @brief Write a der-encoded crl to a file - * - * @param this calling object - * @param path path where the file is to be stored - * @param mask file access control rights - * @param force overwrite the file if it already exists - * @return TRUE if successfully written - */ - bool (*write_to_file) (const crl_t *this, const char *path, mode_t mask, bool force); - - /** - * @brief Destroys the crl. - * - * @param this crl to destroy - */ - void (*destroy) (crl_t *this); -}; - -/** - * @brief Read a x509 crl from a DER encoded blob. - * - * @param chunk chunk containing DER encoded data - * @return created crl_t, or NULL if invalid. - * - * @ingroup transforms - */ -crl_t *crl_create_from_chunk(chunk_t chunk); - -/** - * @brief Read a x509 crl from a DER encoded file. - * - * @param filename file containing DER encoded data - * @return created crl_t, or NULL if invalid. - * - * @ingroup transforms - */ -crl_t *crl_create_from_file(const char *filename); - -#endif /* CRL_H_ */ diff --git a/src/libstrongswan/crypto/crypters/aes_cbc_crypter.c b/src/libstrongswan/crypto/crypters/aes_cbc_crypter.c deleted file mode 100644 index 947188af3..000000000 --- a/src/libstrongswan/crypto/crypters/aes_cbc_crypter.c +++ /dev/null @@ -1,1620 +0,0 @@ -/** - * @file aes_cbc_crypter.c - * - * @brief Implementation of aes_cbc_crypter_t - * - */ - - /* - * Copyright (C) 2001 Dr B. R. Gladman <brg@gladman.uk.net> - * Copyright (C) 2005-2006 Martin Willi - * Copyright (C) 2005 Jan Hutter - * Hochschule fuer Technik Rapperswil - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -#include "aes_cbc_crypter.h" - - - -/* - * The number of key schedule words for different block and key lengths - * allowing for method of computation which requires the length to be a - * multiple of the key length. This version of AES implementation supports - * all three keylengths 16, 24 and 32 bytes! - * - * Nk = 4 6 8 - * ------------- - * Nb = 4 | 60 60 64 - * 6 | 96 90 96 - * 8 | 120 120 120 - */ -#define AES_KS_LENGTH 120 -#define AES_RC_LENGTH 29 - -#define AES_BLOCK_SIZE 16 - -typedef struct private_aes_cbc_crypter_t private_aes_cbc_crypter_t; - -/** - * @brief Class implementing the AES symmetric encryption algorithm. - * - * @ingroup crypters - */ -struct private_aes_cbc_crypter_t { - - /** - * Public part of this class. - */ - aes_cbc_crypter_t public; - - /** - * Number of words in the key input block. - */ - u_int32_t aes_Nkey; - - /** - * The number of cipher rounds. - */ - u_int32_t aes_Nrnd; - - /** - * The encryption key schedule. - */ - u_int32_t aes_e_key[AES_KS_LENGTH]; - - /** - * The decryption key schedule. - */ - u_int32_t aes_d_key[AES_KS_LENGTH]; - - /** - * Key size of this AES cypher object. - */ - u_int32_t key_size; - - /** - * Decrypts a block. - * - * No memory gets allocated. - * - * @param this calling object - * @param[in] in_blk block to decrypt - * @param[out] out_blk decrypted data are written to this location - */ - void (*decrypt_block) (const private_aes_cbc_crypter_t *this, const unsigned char in_blk[], unsigned char out_blk[]); - - /** - * Encrypts a block. - * - * No memory gets allocated. - * - * @param this calling object - * @param[in] in_blk block to encrypt - * @param[out] out_blk encrypted data are written to this location - */ - void (*encrypt_block) (const private_aes_cbc_crypter_t *this, const unsigned char in_blk[], unsigned char out_blk[]); -}; - - -/* ugly macro stuff */ - -/* 1. Define UNROLL for full loop unrolling in encryption and decryption. - * 2. Define PARTIAL_UNROLL to unroll two loops in encryption and decryption. - * 3. Define FIXED_TABLES for compiled rather than dynamic tables. - * 4. Define FF_TABLES to use tables for field multiplies and inverses. - * Do not enable this without understanding stack space requirements. - * 5. Define ARRAYS to use arrays to hold the local state block. If this - * is not defined, individually declared 32-bit words are used. - * 6. Define FAST_VARIABLE if a high speed variable block implementation - * is needed (essentially three separate fixed block size code sequences) - * 7. Define either ONE_TABLE or FOUR_TABLES for a fast table driven - * version using 1 table (2 kbytes of table space) or 4 tables (8 - * kbytes of table space) for higher speed. - * 8. Define either ONE_LR_TABLE or FOUR_LR_TABLES for a further speed - * increase by using tables for the last rounds but with more table - * space (2 or 8 kbytes extra). - * 9. If neither ONE_TABLE nor FOUR_TABLES is defined, a compact but - * slower version is provided. - * 10. If fast decryption key scheduling is needed define ONE_IM_TABLE - * or FOUR_IM_TABLES for higher speed (2 or 8 kbytes extra). - */ - -#define UNROLL -//#define PARTIAL_UNROLL - -#define FIXED_TABLES -//#define FF_TABLES -//#define ARRAYS -#define FAST_VARIABLE - -//#define ONE_TABLE -#define FOUR_TABLES - -//#define ONE_LR_TABLE -#define FOUR_LR_TABLES - -//#define ONE_IM_TABLE -#define FOUR_IM_TABLES - -#if defined(UNROLL) && defined (PARTIAL_UNROLL) -#error both UNROLL and PARTIAL_UNROLL are defined -#endif - -#if defined(ONE_TABLE) && defined (FOUR_TABLES) -#error both ONE_TABLE and FOUR_TABLES are defined -#endif - -#if defined(ONE_LR_TABLE) && defined (FOUR_LR_TABLES) -#error both ONE_LR_TABLE and FOUR_LR_TABLES are defined -#endif - -#if defined(ONE_IM_TABLE) && defined (FOUR_IM_TABLES) -#error both ONE_IM_TABLE and FOUR_IM_TABLES are defined -#endif - -#if defined(AES_BLOCK_SIZE) && AES_BLOCK_SIZE != 16 && AES_BLOCK_SIZE != 24 && AES_BLOCK_SIZE != 32 -#error an illegal block size has been specified -#endif - -/** - * Rotates bytes within words by n positions, moving bytes - * to higher index positions with wrap around into low positions. - */ -#define upr(x,n) (((x) << 8 * (n)) | ((x) >> (32 - 8 * (n)))) -/** - * Moves bytes by n positions to higher index positions in - * words but without wrap around. - */ -#define ups(x,n) ((x) << 8 * (n)) - -/** - * Extracts a byte from a word. - */ -#define bval(x,n) ((unsigned char)((x) >> 8 * (n))) -#define bytes2word(b0, b1, b2, b3) \ - ((u_int32_t)(b3) << 24 | (u_int32_t)(b2) << 16 | (u_int32_t)(b1) << 8 | (b0)) - - -/* little endian processor without data alignment restrictions: AES_LE_OK */ -/* original code: i386 */ -#if defined(i386) || defined(_I386) || defined(__i386__) || defined(__i386) -#define AES_LE_OK 1 -/* added (tested): alpha --jjo */ -#elif defined(__alpha__)|| defined (__alpha) -#define AES_LE_OK 1 -/* added (tested): ia64 --jjo */ -#elif defined(__ia64__)|| defined (__ia64) -#define AES_LE_OK 1 -#endif - -#ifdef AES_LE_OK -/* little endian processor without data alignment restrictions */ -#define word_in(x) *(u_int32_t*)(x) -#define const_word_in(x) *(const u_int32_t*)(x) -#define word_out(x,v) *(u_int32_t*)(x) = (v) -#define const_word_out(x,v) *(const u_int32_t*)(x) = (v) -#else -/* slower but generic big endian or with data alignment restrictions */ -/* some additional "const" touches to stop "gcc -Wcast-qual" complains --jjo */ -#define word_in(x) ((u_int32_t)(((unsigned char *)(x))[0])|((u_int32_t)(((unsigned char *)(x))[1])<<8)|((u_int32_t)(((unsigned char *)(x))[2])<<16)|((u_int32_t)(((unsigned char *)(x))[3])<<24)) -#define const_word_in(x) ((const u_int32_t)(((const unsigned char *)(x))[0])|((const u_int32_t)(((const unsigned char *)(x))[1])<<8)|((const u_int32_t)(((const unsigned char *)(x))[2])<<16)|((const u_int32_t)(((const unsigned char *)(x))[3])<<24)) -#define word_out(x,v) ((unsigned char *)(x))[0]=(v),((unsigned char *)(x))[1]=((v)>>8),((unsigned char *)(x))[2]=((v)>>16),((unsigned char *)(x))[3]=((v)>>24) -#define const_word_out(x,v) ((const unsigned char *)(x))[0]=(v),((const unsigned char *)(x))[1]=((v)>>8),((const unsigned char *)(x))[2]=((v)>>16),((const unsigned char *)(x))[3]=((v)>>24) -#endif - -// Disable at least some poor combinations of options - -#if !defined(ONE_TABLE) && !defined(FOUR_TABLES) -#define FIXED_TABLES -#undef UNROLL -#undef ONE_LR_TABLE -#undef FOUR_LR_TABLES -#undef ONE_IM_TABLE -#undef FOUR_IM_TABLES -#elif !defined(FOUR_TABLES) -#ifdef FOUR_LR_TABLES -#undef FOUR_LR_TABLES -#define ONE_LR_TABLE -#endif -#ifdef FOUR_IM_TABLES -#undef FOUR_IM_TABLES -#define ONE_IM_TABLE -#endif -#elif !defined(AES_BLOCK_SIZE) -#if defined(UNROLL) -#define PARTIAL_UNROLL -#undef UNROLL -#endif -#endif - -// the finite field modular polynomial and elements - -#define ff_poly 0x011b -#define ff_hi 0x80 - -// multiply four bytes in GF(2^8) by 'x' {02} in parallel - -#define m1 0x80808080 -#define m2 0x7f7f7f7f -#define m3 0x0000001b -#define FFmulX(x) ((((x) & m2) << 1) ^ ((((x) & m1) >> 7) * m3)) - -// The following defines provide alternative definitions of FFmulX that might -// give improved performance if a fast 32-bit multiply is not available. Note -// that a temporary variable u needs to be defined where FFmulX is used. - -// #define FFmulX(x) (u = (x) & m1, u |= (u >> 1), ((x) & m2) << 1) ^ ((u >> 3) | (u >> 6)) -// #define m4 0x1b1b1b1b -// #define FFmulX(x) (u = (x) & m1, ((x) & m2) << 1) ^ ((u - (u >> 7)) & m4) - -// perform column mix operation on four bytes in parallel - -#define fwd_mcol(x) (f2 = FFmulX(x), f2 ^ upr(x ^ f2,3) ^ upr(x,2) ^ upr(x,1)) - -#if defined(FIXED_TABLES) - -// the S-Box table - -static const unsigned char s_box[256] = -{ - 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, - 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, - 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, - 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, - 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, - 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, - 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, - 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, - 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, - 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, - 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, - 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, - 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, - 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, - 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, - 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, - 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, - 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, - 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, - 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, - 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, - 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, - 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, - 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, - 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, - 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, - 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, - 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, - 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, - 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, - 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, - 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16 -}; - -// the inverse S-Box table - -static const unsigned char inv_s_box[256] = -{ - 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, - 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb, - 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, - 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb, - 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, - 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e, - 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, - 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25, - 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, - 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92, - 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, - 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84, - 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, - 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06, - 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, - 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b, - 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, - 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73, - 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, - 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e, - 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, - 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b, - 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, - 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4, - 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, - 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f, - 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, - 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef, - 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, - 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61, - 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, - 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d -}; - -#define w0(p) 0x000000##p - -// Number of elements required in this table for different -// block and key lengths is: -// -// Nk = 4 6 8 -// ---------- -// Nb = 4 | 10 8 7 -// 6 | 19 12 11 -// 8 | 29 19 14 -// -// this table can be a table of bytes if the key schedule -// code is adjusted accordingly - -static const u_int32_t rcon_tab[29] = -{ - w0(01), w0(02), w0(04), w0(08), - w0(10), w0(20), w0(40), w0(80), - w0(1b), w0(36), w0(6c), w0(d8), - w0(ab), w0(4d), w0(9a), w0(2f), - w0(5e), w0(bc), w0(63), w0(c6), - w0(97), w0(35), w0(6a), w0(d4), - w0(b3), w0(7d), w0(fa), w0(ef), - w0(c5) -}; - -#undef w0 - -#define r0(p,q,r,s) 0x##p##q##r##s -#define r1(p,q,r,s) 0x##q##r##s##p -#define r2(p,q,r,s) 0x##r##s##p##q -#define r3(p,q,r,s) 0x##s##p##q##r -#define w0(p) 0x000000##p -#define w1(p) 0x0000##p##00 -#define w2(p) 0x00##p##0000 -#define w3(p) 0x##p##000000 - -#if defined(FIXED_TABLES) && (defined(ONE_TABLE) || defined(FOUR_TABLES)) - -// data for forward tables (other than last round) - -#define f_table \ - r(a5,63,63,c6), r(84,7c,7c,f8), r(99,77,77,ee), r(8d,7b,7b,f6),\ - r(0d,f2,f2,ff), r(bd,6b,6b,d6), r(b1,6f,6f,de), r(54,c5,c5,91),\ - r(50,30,30,60), r(03,01,01,02), r(a9,67,67,ce), r(7d,2b,2b,56),\ - r(19,fe,fe,e7), r(62,d7,d7,b5), r(e6,ab,ab,4d), r(9a,76,76,ec),\ - r(45,ca,ca,8f), r(9d,82,82,1f), r(40,c9,c9,89), r(87,7d,7d,fa),\ - r(15,fa,fa,ef), r(eb,59,59,b2), r(c9,47,47,8e), r(0b,f0,f0,fb),\ - r(ec,ad,ad,41), r(67,d4,d4,b3), r(fd,a2,a2,5f), r(ea,af,af,45),\ - r(bf,9c,9c,23), r(f7,a4,a4,53), r(96,72,72,e4), r(5b,c0,c0,9b),\ - r(c2,b7,b7,75), r(1c,fd,fd,e1), r(ae,93,93,3d), r(6a,26,26,4c),\ - r(5a,36,36,6c), r(41,3f,3f,7e), r(02,f7,f7,f5), r(4f,cc,cc,83),\ - r(5c,34,34,68), r(f4,a5,a5,51), r(34,e5,e5,d1), r(08,f1,f1,f9),\ - r(93,71,71,e2), r(73,d8,d8,ab), r(53,31,31,62), r(3f,15,15,2a),\ - r(0c,04,04,08), r(52,c7,c7,95), r(65,23,23,46), r(5e,c3,c3,9d),\ - r(28,18,18,30), r(a1,96,96,37), r(0f,05,05,0a), r(b5,9a,9a,2f),\ - r(09,07,07,0e), r(36,12,12,24), r(9b,80,80,1b), r(3d,e2,e2,df),\ - r(26,eb,eb,cd), r(69,27,27,4e), r(cd,b2,b2,7f), r(9f,75,75,ea),\ - r(1b,09,09,12), r(9e,83,83,1d), r(74,2c,2c,58), r(2e,1a,1a,34),\ - r(2d,1b,1b,36), r(b2,6e,6e,dc), r(ee,5a,5a,b4), r(fb,a0,a0,5b),\ - r(f6,52,52,a4), r(4d,3b,3b,76), r(61,d6,d6,b7), r(ce,b3,b3,7d),\ - r(7b,29,29,52), r(3e,e3,e3,dd), r(71,2f,2f,5e), r(97,84,84,13),\ - r(f5,53,53,a6), r(68,d1,d1,b9), r(00,00,00,00), r(2c,ed,ed,c1),\ - r(60,20,20,40), r(1f,fc,fc,e3), r(c8,b1,b1,79), r(ed,5b,5b,b6),\ - r(be,6a,6a,d4), r(46,cb,cb,8d), r(d9,be,be,67), r(4b,39,39,72),\ - r(de,4a,4a,94), r(d4,4c,4c,98), r(e8,58,58,b0), r(4a,cf,cf,85),\ - r(6b,d0,d0,bb), r(2a,ef,ef,c5), r(e5,aa,aa,4f), r(16,fb,fb,ed),\ - r(c5,43,43,86), r(d7,4d,4d,9a), r(55,33,33,66), r(94,85,85,11),\ - r(cf,45,45,8a), r(10,f9,f9,e9), r(06,02,02,04), r(81,7f,7f,fe),\ - r(f0,50,50,a0), r(44,3c,3c,78), r(ba,9f,9f,25), r(e3,a8,a8,4b),\ - r(f3,51,51,a2), r(fe,a3,a3,5d), r(c0,40,40,80), r(8a,8f,8f,05),\ - r(ad,92,92,3f), r(bc,9d,9d,21), r(48,38,38,70), r(04,f5,f5,f1),\ - r(df,bc,bc,63), r(c1,b6,b6,77), r(75,da,da,af), r(63,21,21,42),\ - r(30,10,10,20), r(1a,ff,ff,e5), r(0e,f3,f3,fd), r(6d,d2,d2,bf),\ - r(4c,cd,cd,81), r(14,0c,0c,18), r(35,13,13,26), r(2f,ec,ec,c3),\ - r(e1,5f,5f,be), r(a2,97,97,35), r(cc,44,44,88), r(39,17,17,2e),\ - r(57,c4,c4,93), r(f2,a7,a7,55), r(82,7e,7e,fc), r(47,3d,3d,7a),\ - r(ac,64,64,c8), r(e7,5d,5d,ba), r(2b,19,19,32), r(95,73,73,e6),\ - r(a0,60,60,c0), r(98,81,81,19), r(d1,4f,4f,9e), r(7f,dc,dc,a3),\ - r(66,22,22,44), r(7e,2a,2a,54), r(ab,90,90,3b), r(83,88,88,0b),\ - r(ca,46,46,8c), r(29,ee,ee,c7), r(d3,b8,b8,6b), r(3c,14,14,28),\ - r(79,de,de,a7), r(e2,5e,5e,bc), r(1d,0b,0b,16), r(76,db,db,ad),\ - r(3b,e0,e0,db), r(56,32,32,64), r(4e,3a,3a,74), r(1e,0a,0a,14),\ - r(db,49,49,92), r(0a,06,06,0c), r(6c,24,24,48), r(e4,5c,5c,b8),\ - r(5d,c2,c2,9f), r(6e,d3,d3,bd), r(ef,ac,ac,43), r(a6,62,62,c4),\ - r(a8,91,91,39), r(a4,95,95,31), r(37,e4,e4,d3), r(8b,79,79,f2),\ - r(32,e7,e7,d5), r(43,c8,c8,8b), r(59,37,37,6e), r(b7,6d,6d,da),\ - r(8c,8d,8d,01), r(64,d5,d5,b1), r(d2,4e,4e,9c), r(e0,a9,a9,49),\ - r(b4,6c,6c,d8), r(fa,56,56,ac), r(07,f4,f4,f3), r(25,ea,ea,cf),\ - r(af,65,65,ca), r(8e,7a,7a,f4), r(e9,ae,ae,47), r(18,08,08,10),\ - r(d5,ba,ba,6f), r(88,78,78,f0), r(6f,25,25,4a), r(72,2e,2e,5c),\ - r(24,1c,1c,38), r(f1,a6,a6,57), r(c7,b4,b4,73), r(51,c6,c6,97),\ - r(23,e8,e8,cb), r(7c,dd,dd,a1), r(9c,74,74,e8), r(21,1f,1f,3e),\ - r(dd,4b,4b,96), r(dc,bd,bd,61), r(86,8b,8b,0d), r(85,8a,8a,0f),\ - r(90,70,70,e0), r(42,3e,3e,7c), r(c4,b5,b5,71), r(aa,66,66,cc),\ - r(d8,48,48,90), r(05,03,03,06), r(01,f6,f6,f7), r(12,0e,0e,1c),\ - r(a3,61,61,c2), r(5f,35,35,6a), r(f9,57,57,ae), r(d0,b9,b9,69),\ - r(91,86,86,17), r(58,c1,c1,99), r(27,1d,1d,3a), r(b9,9e,9e,27),\ - r(38,e1,e1,d9), r(13,f8,f8,eb), r(b3,98,98,2b), r(33,11,11,22),\ - r(bb,69,69,d2), r(70,d9,d9,a9), r(89,8e,8e,07), r(a7,94,94,33),\ - r(b6,9b,9b,2d), r(22,1e,1e,3c), r(92,87,87,15), r(20,e9,e9,c9),\ - r(49,ce,ce,87), r(ff,55,55,aa), r(78,28,28,50), r(7a,df,df,a5),\ - r(8f,8c,8c,03), r(f8,a1,a1,59), r(80,89,89,09), r(17,0d,0d,1a),\ - r(da,bf,bf,65), r(31,e6,e6,d7), r(c6,42,42,84), r(b8,68,68,d0),\ - r(c3,41,41,82), r(b0,99,99,29), r(77,2d,2d,5a), r(11,0f,0f,1e),\ - r(cb,b0,b0,7b), r(fc,54,54,a8), r(d6,bb,bb,6d), r(3a,16,16,2c) - -// data for inverse tables (other than last round) - -#define i_table \ - r(50,a7,f4,51), r(53,65,41,7e), r(c3,a4,17,1a), r(96,5e,27,3a),\ - r(cb,6b,ab,3b), r(f1,45,9d,1f), r(ab,58,fa,ac), r(93,03,e3,4b),\ - r(55,fa,30,20), r(f6,6d,76,ad), r(91,76,cc,88), r(25,4c,02,f5),\ - r(fc,d7,e5,4f), r(d7,cb,2a,c5), r(80,44,35,26), r(8f,a3,62,b5),\ - r(49,5a,b1,de), r(67,1b,ba,25), r(98,0e,ea,45), r(e1,c0,fe,5d),\ - r(02,75,2f,c3), r(12,f0,4c,81), r(a3,97,46,8d), r(c6,f9,d3,6b),\ - r(e7,5f,8f,03), r(95,9c,92,15), r(eb,7a,6d,bf), r(da,59,52,95),\ - r(2d,83,be,d4), r(d3,21,74,58), r(29,69,e0,49), r(44,c8,c9,8e),\ - r(6a,89,c2,75), r(78,79,8e,f4), r(6b,3e,58,99), r(dd,71,b9,27),\ - r(b6,4f,e1,be), r(17,ad,88,f0), r(66,ac,20,c9), r(b4,3a,ce,7d),\ - r(18,4a,df,63), r(82,31,1a,e5), r(60,33,51,97), r(45,7f,53,62),\ - r(e0,77,64,b1), r(84,ae,6b,bb), r(1c,a0,81,fe), r(94,2b,08,f9),\ - r(58,68,48,70), r(19,fd,45,8f), r(87,6c,de,94), r(b7,f8,7b,52),\ - r(23,d3,73,ab), r(e2,02,4b,72), r(57,8f,1f,e3), r(2a,ab,55,66),\ - r(07,28,eb,b2), r(03,c2,b5,2f), r(9a,7b,c5,86), r(a5,08,37,d3),\ - r(f2,87,28,30), r(b2,a5,bf,23), r(ba,6a,03,02), r(5c,82,16,ed),\ - r(2b,1c,cf,8a), r(92,b4,79,a7), r(f0,f2,07,f3), r(a1,e2,69,4e),\ - r(cd,f4,da,65), r(d5,be,05,06), r(1f,62,34,d1), r(8a,fe,a6,c4),\ - r(9d,53,2e,34), r(a0,55,f3,a2), r(32,e1,8a,05), r(75,eb,f6,a4),\ - r(39,ec,83,0b), r(aa,ef,60,40), r(06,9f,71,5e), r(51,10,6e,bd),\ - r(f9,8a,21,3e), r(3d,06,dd,96), r(ae,05,3e,dd), r(46,bd,e6,4d),\ - r(b5,8d,54,91), r(05,5d,c4,71), r(6f,d4,06,04), r(ff,15,50,60),\ - r(24,fb,98,19), r(97,e9,bd,d6), r(cc,43,40,89), r(77,9e,d9,67),\ - r(bd,42,e8,b0), r(88,8b,89,07), r(38,5b,19,e7), r(db,ee,c8,79),\ - r(47,0a,7c,a1), r(e9,0f,42,7c), r(c9,1e,84,f8), r(00,00,00,00),\ - r(83,86,80,09), r(48,ed,2b,32), r(ac,70,11,1e), r(4e,72,5a,6c),\ - r(fb,ff,0e,fd), r(56,38,85,0f), r(1e,d5,ae,3d), r(27,39,2d,36),\ - r(64,d9,0f,0a), r(21,a6,5c,68), r(d1,54,5b,9b), r(3a,2e,36,24),\ - r(b1,67,0a,0c), r(0f,e7,57,93), r(d2,96,ee,b4), r(9e,91,9b,1b),\ - r(4f,c5,c0,80), r(a2,20,dc,61), r(69,4b,77,5a), r(16,1a,12,1c),\ - r(0a,ba,93,e2), r(e5,2a,a0,c0), r(43,e0,22,3c), r(1d,17,1b,12),\ - r(0b,0d,09,0e), r(ad,c7,8b,f2), r(b9,a8,b6,2d), r(c8,a9,1e,14),\ - r(85,19,f1,57), r(4c,07,75,af), r(bb,dd,99,ee), r(fd,60,7f,a3),\ - r(9f,26,01,f7), r(bc,f5,72,5c), r(c5,3b,66,44), r(34,7e,fb,5b),\ - r(76,29,43,8b), r(dc,c6,23,cb), r(68,fc,ed,b6), r(63,f1,e4,b8),\ - r(ca,dc,31,d7), r(10,85,63,42), r(40,22,97,13), r(20,11,c6,84),\ - r(7d,24,4a,85), r(f8,3d,bb,d2), r(11,32,f9,ae), r(6d,a1,29,c7),\ - r(4b,2f,9e,1d), r(f3,30,b2,dc), r(ec,52,86,0d), r(d0,e3,c1,77),\ - r(6c,16,b3,2b), r(99,b9,70,a9), r(fa,48,94,11), r(22,64,e9,47),\ - r(c4,8c,fc,a8), r(1a,3f,f0,a0), r(d8,2c,7d,56), r(ef,90,33,22),\ - r(c7,4e,49,87), r(c1,d1,38,d9), r(fe,a2,ca,8c), r(36,0b,d4,98),\ - r(cf,81,f5,a6), r(28,de,7a,a5), r(26,8e,b7,da), r(a4,bf,ad,3f),\ - r(e4,9d,3a,2c), r(0d,92,78,50), r(9b,cc,5f,6a), r(62,46,7e,54),\ - r(c2,13,8d,f6), r(e8,b8,d8,90), r(5e,f7,39,2e), r(f5,af,c3,82),\ - r(be,80,5d,9f), r(7c,93,d0,69), r(a9,2d,d5,6f), r(b3,12,25,cf),\ - r(3b,99,ac,c8), r(a7,7d,18,10), r(6e,63,9c,e8), r(7b,bb,3b,db),\ - r(09,78,26,cd), r(f4,18,59,6e), r(01,b7,9a,ec), r(a8,9a,4f,83),\ - r(65,6e,95,e6), r(7e,e6,ff,aa), r(08,cf,bc,21), r(e6,e8,15,ef),\ - r(d9,9b,e7,ba), r(ce,36,6f,4a), r(d4,09,9f,ea), r(d6,7c,b0,29),\ - r(af,b2,a4,31), r(31,23,3f,2a), r(30,94,a5,c6), r(c0,66,a2,35),\ - r(37,bc,4e,74), r(a6,ca,82,fc), r(b0,d0,90,e0), r(15,d8,a7,33),\ - r(4a,98,04,f1), r(f7,da,ec,41), r(0e,50,cd,7f), r(2f,f6,91,17),\ - r(8d,d6,4d,76), r(4d,b0,ef,43), r(54,4d,aa,cc), r(df,04,96,e4),\ - r(e3,b5,d1,9e), r(1b,88,6a,4c), r(b8,1f,2c,c1), r(7f,51,65,46),\ - r(04,ea,5e,9d), r(5d,35,8c,01), r(73,74,87,fa), r(2e,41,0b,fb),\ - r(5a,1d,67,b3), r(52,d2,db,92), r(33,56,10,e9), r(13,47,d6,6d),\ - r(8c,61,d7,9a), r(7a,0c,a1,37), r(8e,14,f8,59), r(89,3c,13,eb),\ - r(ee,27,a9,ce), r(35,c9,61,b7), r(ed,e5,1c,e1), r(3c,b1,47,7a),\ - r(59,df,d2,9c), r(3f,73,f2,55), r(79,ce,14,18), r(bf,37,c7,73),\ - r(ea,cd,f7,53), r(5b,aa,fd,5f), r(14,6f,3d,df), r(86,db,44,78),\ - r(81,f3,af,ca), r(3e,c4,68,b9), r(2c,34,24,38), r(5f,40,a3,c2),\ - r(72,c3,1d,16), r(0c,25,e2,bc), r(8b,49,3c,28), r(41,95,0d,ff),\ - r(71,01,a8,39), r(de,b3,0c,08), r(9c,e4,b4,d8), r(90,c1,56,64),\ - r(61,84,cb,7b), r(70,b6,32,d5), r(74,5c,6c,48), r(42,57,b8,d0) - -// generate the required tables in the desired endian format - -#undef r -#define r r0 - -#if defined(ONE_TABLE) -static const u_int32_t ft_tab[256] = - { f_table }; -#elif defined(FOUR_TABLES) -static const u_int32_t ft_tab[4][256] = -{ { f_table }, -#undef r -#define r r1 - { f_table }, -#undef r -#define r r2 - { f_table }, -#undef r -#define r r3 - { f_table } -}; -#endif - -#undef r -#define r r0 -#if defined(ONE_TABLE) -static const u_int32_t it_tab[256] = - { i_table }; -#elif defined(FOUR_TABLES) -static const u_int32_t it_tab[4][256] = -{ { i_table }, -#undef r -#define r r1 - { i_table }, -#undef r -#define r r2 - { i_table }, -#undef r -#define r r3 - { i_table } -}; -#endif - -#endif - -#if defined(FIXED_TABLES) && (defined(ONE_LR_TABLE) || defined(FOUR_LR_TABLES)) - -// data for inverse tables (last round) - -#define li_table \ - w(52), w(09), w(6a), w(d5), w(30), w(36), w(a5), w(38),\ - w(bf), w(40), w(a3), w(9e), w(81), w(f3), w(d7), w(fb),\ - w(7c), w(e3), w(39), w(82), w(9b), w(2f), w(ff), w(87),\ - w(34), w(8e), w(43), w(44), w(c4), w(de), w(e9), w(cb),\ - w(54), w(7b), w(94), w(32), w(a6), w(c2), w(23), w(3d),\ - w(ee), w(4c), w(95), w(0b), w(42), w(fa), w(c3), w(4e),\ - w(08), w(2e), w(a1), w(66), w(28), w(d9), w(24), w(b2),\ - w(76), w(5b), w(a2), w(49), w(6d), w(8b), w(d1), w(25),\ - w(72), w(f8), w(f6), w(64), w(86), w(68), w(98), w(16),\ - w(d4), w(a4), w(5c), w(cc), w(5d), w(65), w(b6), w(92),\ - w(6c), w(70), w(48), w(50), w(fd), w(ed), w(b9), w(da),\ - w(5e), w(15), w(46), w(57), w(a7), w(8d), w(9d), w(84),\ - w(90), w(d8), w(ab), w(00), w(8c), w(bc), w(d3), w(0a),\ - w(f7), w(e4), w(58), w(05), w(b8), w(b3), w(45), w(06),\ - w(d0), w(2c), w(1e), w(8f), w(ca), w(3f), w(0f), w(02),\ - w(c1), w(af), w(bd), w(03), w(01), w(13), w(8a), w(6b),\ - w(3a), w(91), w(11), w(41), w(4f), w(67), w(dc), w(ea),\ - w(97), w(f2), w(cf), w(ce), w(f0), w(b4), w(e6), w(73),\ - w(96), w(ac), w(74), w(22), w(e7), w(ad), w(35), w(85),\ - w(e2), w(f9), w(37), w(e8), w(1c), w(75), w(df), w(6e),\ - w(47), w(f1), w(1a), w(71), w(1d), w(29), w(c5), w(89),\ - w(6f), w(b7), w(62), w(0e), w(aa), w(18), w(be), w(1b),\ - w(fc), w(56), w(3e), w(4b), w(c6), w(d2), w(79), w(20),\ - w(9a), w(db), w(c0), w(fe), w(78), w(cd), w(5a), w(f4),\ - w(1f), w(dd), w(a8), w(33), w(88), w(07), w(c7), w(31),\ - w(b1), w(12), w(10), w(59), w(27), w(80), w(ec), w(5f),\ - w(60), w(51), w(7f), w(a9), w(19), w(b5), w(4a), w(0d),\ - w(2d), w(e5), w(7a), w(9f), w(93), w(c9), w(9c), w(ef),\ - w(a0), w(e0), w(3b), w(4d), w(ae), w(2a), w(f5), w(b0),\ - w(c8), w(eb), w(bb), w(3c), w(83), w(53), w(99), w(61),\ - w(17), w(2b), w(04), w(7e), w(ba), w(77), w(d6), w(26),\ - w(e1), w(69), w(14), w(63), w(55), w(21), w(0c), w(7d), - -// generate the required tables in the desired endian format - -#undef r -#define r(p,q,r,s) w0(q) -#if defined(ONE_LR_TABLE) -static const u_int32_t fl_tab[256] = - { f_table }; -#elif defined(FOUR_LR_TABLES) -static const u_int32_t fl_tab[4][256] = -{ { f_table }, -#undef r -#define r(p,q,r,s) w1(q) - { f_table }, -#undef r -#define r(p,q,r,s) w2(q) - { f_table }, -#undef r -#define r(p,q,r,s) w3(q) - { f_table } -}; -#endif - -#undef w -#define w w0 -#if defined(ONE_LR_TABLE) -static const u_int32_t il_tab[256] = - { li_table }; -#elif defined(FOUR_LR_TABLES) -static const u_int32_t il_tab[4][256] = -{ { li_table }, -#undef w -#define w w1 - { li_table }, -#undef w -#define w w2 - { li_table }, -#undef w -#define w w3 - { li_table } -}; -#endif - -#endif - -#if defined(FIXED_TABLES) && (defined(ONE_IM_TABLE) || defined(FOUR_IM_TABLES)) - -#define m_table \ - r(00,00,00,00), r(0b,0d,09,0e), r(16,1a,12,1c), r(1d,17,1b,12),\ - r(2c,34,24,38), r(27,39,2d,36), r(3a,2e,36,24), r(31,23,3f,2a),\ - r(58,68,48,70), r(53,65,41,7e), r(4e,72,5a,6c), r(45,7f,53,62),\ - r(74,5c,6c,48), r(7f,51,65,46), r(62,46,7e,54), r(69,4b,77,5a),\ - r(b0,d0,90,e0), r(bb,dd,99,ee), r(a6,ca,82,fc), r(ad,c7,8b,f2),\ - r(9c,e4,b4,d8), r(97,e9,bd,d6), r(8a,fe,a6,c4), r(81,f3,af,ca),\ - r(e8,b8,d8,90), r(e3,b5,d1,9e), r(fe,a2,ca,8c), r(f5,af,c3,82),\ - r(c4,8c,fc,a8), r(cf,81,f5,a6), r(d2,96,ee,b4), r(d9,9b,e7,ba),\ - r(7b,bb,3b,db), r(70,b6,32,d5), r(6d,a1,29,c7), r(66,ac,20,c9),\ - r(57,8f,1f,e3), r(5c,82,16,ed), r(41,95,0d,ff), r(4a,98,04,f1),\ - r(23,d3,73,ab), r(28,de,7a,a5), r(35,c9,61,b7), r(3e,c4,68,b9),\ - r(0f,e7,57,93), r(04,ea,5e,9d), r(19,fd,45,8f), r(12,f0,4c,81),\ - r(cb,6b,ab,3b), r(c0,66,a2,35), r(dd,71,b9,27), r(d6,7c,b0,29),\ - r(e7,5f,8f,03), r(ec,52,86,0d), r(f1,45,9d,1f), r(fa,48,94,11),\ - r(93,03,e3,4b), r(98,0e,ea,45), r(85,19,f1,57), r(8e,14,f8,59),\ - r(bf,37,c7,73), r(b4,3a,ce,7d), r(a9,2d,d5,6f), r(a2,20,dc,61),\ - r(f6,6d,76,ad), r(fd,60,7f,a3), r(e0,77,64,b1), r(eb,7a,6d,bf),\ - r(da,59,52,95), r(d1,54,5b,9b), r(cc,43,40,89), r(c7,4e,49,87),\ - r(ae,05,3e,dd), r(a5,08,37,d3), r(b8,1f,2c,c1), r(b3,12,25,cf),\ - r(82,31,1a,e5), r(89,3c,13,eb), r(94,2b,08,f9), r(9f,26,01,f7),\ - r(46,bd,e6,4d), r(4d,b0,ef,43), r(50,a7,f4,51), r(5b,aa,fd,5f),\ - r(6a,89,c2,75), r(61,84,cb,7b), r(7c,93,d0,69), r(77,9e,d9,67),\ - r(1e,d5,ae,3d), r(15,d8,a7,33), r(08,cf,bc,21), r(03,c2,b5,2f),\ - r(32,e1,8a,05), r(39,ec,83,0b), r(24,fb,98,19), r(2f,f6,91,17),\ - r(8d,d6,4d,76), r(86,db,44,78), r(9b,cc,5f,6a), r(90,c1,56,64),\ - r(a1,e2,69,4e), r(aa,ef,60,40), r(b7,f8,7b,52), r(bc,f5,72,5c),\ - r(d5,be,05,06), r(de,b3,0c,08), r(c3,a4,17,1a), r(c8,a9,1e,14),\ - r(f9,8a,21,3e), r(f2,87,28,30), r(ef,90,33,22), r(e4,9d,3a,2c),\ - r(3d,06,dd,96), r(36,0b,d4,98), r(2b,1c,cf,8a), r(20,11,c6,84),\ - r(11,32,f9,ae), r(1a,3f,f0,a0), r(07,28,eb,b2), r(0c,25,e2,bc),\ - r(65,6e,95,e6), r(6e,63,9c,e8), r(73,74,87,fa), r(78,79,8e,f4),\ - r(49,5a,b1,de), r(42,57,b8,d0), r(5f,40,a3,c2), r(54,4d,aa,cc),\ - r(f7,da,ec,41), r(fc,d7,e5,4f), r(e1,c0,fe,5d), r(ea,cd,f7,53),\ - r(db,ee,c8,79), r(d0,e3,c1,77), r(cd,f4,da,65), r(c6,f9,d3,6b),\ - r(af,b2,a4,31), r(a4,bf,ad,3f), r(b9,a8,b6,2d), r(b2,a5,bf,23),\ - r(83,86,80,09), r(88,8b,89,07), r(95,9c,92,15), r(9e,91,9b,1b),\ - r(47,0a,7c,a1), r(4c,07,75,af), r(51,10,6e,bd), r(5a,1d,67,b3),\ - r(6b,3e,58,99), r(60,33,51,97), r(7d,24,4a,85), r(76,29,43,8b),\ - r(1f,62,34,d1), r(14,6f,3d,df), r(09,78,26,cd), r(02,75,2f,c3),\ - r(33,56,10,e9), r(38,5b,19,e7), r(25,4c,02,f5), r(2e,41,0b,fb),\ - r(8c,61,d7,9a), r(87,6c,de,94), r(9a,7b,c5,86), r(91,76,cc,88),\ - r(a0,55,f3,a2), r(ab,58,fa,ac), r(b6,4f,e1,be), r(bd,42,e8,b0),\ - r(d4,09,9f,ea), r(df,04,96,e4), r(c2,13,8d,f6), r(c9,1e,84,f8),\ - r(f8,3d,bb,d2), r(f3,30,b2,dc), r(ee,27,a9,ce), r(e5,2a,a0,c0),\ - r(3c,b1,47,7a), r(37,bc,4e,74), r(2a,ab,55,66), r(21,a6,5c,68),\ - r(10,85,63,42), r(1b,88,6a,4c), r(06,9f,71,5e), r(0d,92,78,50),\ - r(64,d9,0f,0a), r(6f,d4,06,04), r(72,c3,1d,16), r(79,ce,14,18),\ - r(48,ed,2b,32), r(43,e0,22,3c), r(5e,f7,39,2e), r(55,fa,30,20),\ - r(01,b7,9a,ec), r(0a,ba,93,e2), r(17,ad,88,f0), r(1c,a0,81,fe),\ - r(2d,83,be,d4), r(26,8e,b7,da), r(3b,99,ac,c8), r(30,94,a5,c6),\ - r(59,df,d2,9c), r(52,d2,db,92), r(4f,c5,c0,80), r(44,c8,c9,8e),\ - r(75,eb,f6,a4), r(7e,e6,ff,aa), r(63,f1,e4,b8), r(68,fc,ed,b6),\ - r(b1,67,0a,0c), r(ba,6a,03,02), r(a7,7d,18,10), r(ac,70,11,1e),\ - r(9d,53,2e,34), r(96,5e,27,3a), r(8b,49,3c,28), r(80,44,35,26),\ - r(e9,0f,42,7c), r(e2,02,4b,72), r(ff,15,50,60), r(f4,18,59,6e),\ - r(c5,3b,66,44), r(ce,36,6f,4a), r(d3,21,74,58), r(d8,2c,7d,56),\ - r(7a,0c,a1,37), r(71,01,a8,39), r(6c,16,b3,2b), r(67,1b,ba,25),\ - r(56,38,85,0f), r(5d,35,8c,01), r(40,22,97,13), r(4b,2f,9e,1d),\ - r(22,64,e9,47), r(29,69,e0,49), r(34,7e,fb,5b), r(3f,73,f2,55),\ - r(0e,50,cd,7f), r(05,5d,c4,71), r(18,4a,df,63), r(13,47,d6,6d),\ - r(ca,dc,31,d7), r(c1,d1,38,d9), r(dc,c6,23,cb), r(d7,cb,2a,c5),\ - r(e6,e8,15,ef), r(ed,e5,1c,e1), r(f0,f2,07,f3), r(fb,ff,0e,fd),\ - r(92,b4,79,a7), r(99,b9,70,a9), r(84,ae,6b,bb), r(8f,a3,62,b5),\ - r(be,80,5d,9f), r(b5,8d,54,91), r(a8,9a,4f,83), r(a3,97,46,8d) - -#undef r -#define r r0 - -#if defined(ONE_IM_TABLE) -static const u_int32_t im_tab[256] = - { m_table }; -#elif defined(FOUR_IM_TABLES) -static const u_int32_t im_tab[4][256] = -{ { m_table }, -#undef r -#define r r1 - { m_table }, -#undef r -#define r r2 - { m_table }, -#undef r -#define r r3 - { m_table } -}; -#endif - -#endif - -#else - -static int tab_gen = 0; - -static unsigned char s_box[256]; // the S box -static unsigned char inv_s_box[256]; // the inverse S box -static u_int32_t rcon_tab[AES_RC_LENGTH]; // table of round constants - -#if defined(ONE_TABLE) -static u_int32_t ft_tab[256]; -static u_int32_t it_tab[256]; -#elif defined(FOUR_TABLES) -static u_int32_t ft_tab[4][256]; -static u_int32_t it_tab[4][256]; -#endif - -#if defined(ONE_LR_TABLE) -static u_int32_t fl_tab[256]; -static u_int32_t il_tab[256]; -#elif defined(FOUR_LR_TABLES) -static u_int32_t fl_tab[4][256]; -static u_int32_t il_tab[4][256]; -#endif - -#if defined(ONE_IM_TABLE) -static u_int32_t im_tab[256]; -#elif defined(FOUR_IM_TABLES) -static u_int32_t im_tab[4][256]; -#endif - -// Generate the tables for the dynamic table option - -#if !defined(FF_TABLES) - -// It will generally be sensible to use tables to compute finite -// field multiplies and inverses but where memory is scarse this -// code might sometimes be better. - -// return 2 ^ (n - 1) where n is the bit number of the highest bit -// set in x with x in the range 1 < x < 0x00000200. This form is -// used so that locals within FFinv can be bytes rather than words - -static unsigned char hibit(const u_int32_t x) -{ unsigned char r = (unsigned char)((x >> 1) | (x >> 2)); - - r |= (r >> 2); - r |= (r >> 4); - return (r + 1) >> 1; -} - -// return the inverse of the finite field element x - -static unsigned char FFinv(const unsigned char x) -{ unsigned char p1 = x, p2 = 0x1b, n1 = hibit(x), n2 = 0x80, v1 = 1, v2 = 0; - - if(x < 2) return x; - - for(;;) - { - if(!n1) return v1; - - while(n2 >= n1) - { - n2 /= n1; p2 ^= p1 * n2; v2 ^= v1 * n2; n2 = hibit(p2); - } - - if(!n2) return v2; - - while(n1 >= n2) - { - n1 /= n2; p1 ^= p2 * n1; v1 ^= v2 * n1; n1 = hibit(p1); - } - } -} - -// define the finite field multiplies required for Rijndael - -#define FFmul02(x) ((((x) & 0x7f) << 1) ^ ((x) & 0x80 ? 0x1b : 0)) -#define FFmul03(x) ((x) ^ FFmul02(x)) -#define FFmul09(x) ((x) ^ FFmul02(FFmul02(FFmul02(x)))) -#define FFmul0b(x) ((x) ^ FFmul02((x) ^ FFmul02(FFmul02(x)))) -#define FFmul0d(x) ((x) ^ FFmul02(FFmul02((x) ^ FFmul02(x)))) -#define FFmul0e(x) FFmul02((x) ^ FFmul02((x) ^ FFmul02(x))) - -#else - -#define FFinv(x) ((x) ? pow[255 - log[x]]: 0) - -#define FFmul02(x) (x ? pow[log[x] + 0x19] : 0) -#define FFmul03(x) (x ? pow[log[x] + 0x01] : 0) -#define FFmul09(x) (x ? pow[log[x] + 0xc7] : 0) -#define FFmul0b(x) (x ? pow[log[x] + 0x68] : 0) -#define FFmul0d(x) (x ? pow[log[x] + 0xee] : 0) -#define FFmul0e(x) (x ? pow[log[x] + 0xdf] : 0) - -#endif - -// The forward and inverse affine transformations used in the S-box - -#define fwd_affine(x) \ - (w = (u_int32_t)x, w ^= (w<<1)^(w<<2)^(w<<3)^(w<<4), 0x63^(unsigned char)(w^(w>>8))) - -#define inv_affine(x) \ - (w = (u_int32_t)x, w = (w<<1)^(w<<3)^(w<<6), 0x05^(unsigned char)(w^(w>>8))) - -static void gen_tabs(void) -{ u_int32_t i, w; - -#if defined(FF_TABLES) - - unsigned char pow[512], log[256]; - - // log and power tables for GF(2^8) finite field with - // 0x011b as modular polynomial - the simplest primitive - // root is 0x03, used here to generate the tables - - i = 0; w = 1; - do - { - pow[i] = (unsigned char)w; - pow[i + 255] = (unsigned char)w; - log[w] = (unsigned char)i++; - w ^= (w << 1) ^ (w & ff_hi ? ff_poly : 0); - } - while (w != 1); - -#endif - - for(i = 0, w = 1; i < AES_RC_LENGTH; ++i) - { - rcon_tab[i] = bytes2word(w, 0, 0, 0); - w = (w << 1) ^ (w & ff_hi ? ff_poly : 0); - } - - for(i = 0; i < 256; ++i) - { unsigned char b; - - s_box[i] = b = fwd_affine(FFinv((unsigned char)i)); - - w = bytes2word(b, 0, 0, 0); -#if defined(ONE_LR_TABLE) - fl_tab[i] = w; -#elif defined(FOUR_LR_TABLES) - fl_tab[0][i] = w; - fl_tab[1][i] = upr(w,1); - fl_tab[2][i] = upr(w,2); - fl_tab[3][i] = upr(w,3); -#endif - w = bytes2word(FFmul02(b), b, b, FFmul03(b)); -#if defined(ONE_TABLE) - ft_tab[i] = w; -#elif defined(FOUR_TABLES) - ft_tab[0][i] = w; - ft_tab[1][i] = upr(w,1); - ft_tab[2][i] = upr(w,2); - ft_tab[3][i] = upr(w,3); -#endif - inv_s_box[i] = b = FFinv(inv_affine((unsigned char)i)); - - w = bytes2word(b, 0, 0, 0); -#if defined(ONE_LR_TABLE) - il_tab[i] = w; -#elif defined(FOUR_LR_TABLES) - il_tab[0][i] = w; - il_tab[1][i] = upr(w,1); - il_tab[2][i] = upr(w,2); - il_tab[3][i] = upr(w,3); -#endif - w = bytes2word(FFmul0e(b), FFmul09(b), FFmul0d(b), FFmul0b(b)); -#if defined(ONE_TABLE) - it_tab[i] = w; -#elif defined(FOUR_TABLES) - it_tab[0][i] = w; - it_tab[1][i] = upr(w,1); - it_tab[2][i] = upr(w,2); - it_tab[3][i] = upr(w,3); -#endif -#if defined(ONE_IM_TABLE) - im_tab[b] = w; -#elif defined(FOUR_IM_TABLES) - im_tab[0][b] = w; - im_tab[1][b] = upr(w,1); - im_tab[2][b] = upr(w,2); - im_tab[3][b] = upr(w,3); -#endif - - } -} - -#endif - -#define no_table(x,box,vf,rf,c) bytes2word( \ - box[bval(vf(x,0,c),rf(0,c))], \ - box[bval(vf(x,1,c),rf(1,c))], \ - box[bval(vf(x,2,c),rf(2,c))], \ - box[bval(vf(x,3,c),rf(3,c))]) - -#define one_table(x,op,tab,vf,rf,c) \ - ( tab[bval(vf(x,0,c),rf(0,c))] \ - ^ op(tab[bval(vf(x,1,c),rf(1,c))],1) \ - ^ op(tab[bval(vf(x,2,c),rf(2,c))],2) \ - ^ op(tab[bval(vf(x,3,c),rf(3,c))],3)) - -#define four_tables(x,tab,vf,rf,c) \ - ( tab[0][bval(vf(x,0,c),rf(0,c))] \ - ^ tab[1][bval(vf(x,1,c),rf(1,c))] \ - ^ tab[2][bval(vf(x,2,c),rf(2,c))] \ - ^ tab[3][bval(vf(x,3,c),rf(3,c))]) - -#define vf1(x,r,c) (x) -#define rf1(r,c) (r) -#define rf2(r,c) ((r-c)&3) - -#if defined(FOUR_LR_TABLES) -#define ls_box(x,c) four_tables(x,fl_tab,vf1,rf2,c) -#elif defined(ONE_LR_TABLE) -#define ls_box(x,c) one_table(x,upr,fl_tab,vf1,rf2,c) -#else -#define ls_box(x,c) no_table(x,s_box,vf1,rf2,c) -#endif - -#if defined(FOUR_IM_TABLES) -#define inv_mcol(x) four_tables(x,im_tab,vf1,rf1,0) -#elif defined(ONE_IM_TABLE) -#define inv_mcol(x) one_table(x,upr,im_tab,vf1,rf1,0) -#else -#define inv_mcol(x) \ - (f9 = (x),f2 = FFmulX(f9), f4 = FFmulX(f2), f8 = FFmulX(f4), f9 ^= f8, \ - f2 ^= f4 ^ f8 ^ upr(f2 ^ f9,3) ^ upr(f4 ^ f9,2) ^ upr(f9,1)) -#endif - -#define nc (AES_BLOCK_SIZE/4) - -// Initialise the key schedule from the user supplied key. The key -// length is now specified in bytes - 16, 24 or 32 as appropriate. -// This corresponds to bit lengths of 128, 192 and 256 bits, and -// to Nk values of 4, 6 and 8 respectively. - -#define mx(t,f) (*t++ = inv_mcol(*f),f++) -#define cp(t,f) *t++ = *f++ - -#if AES_BLOCK_SIZE == 16 -#define cpy(d,s) cp(d,s); cp(d,s); cp(d,s); cp(d,s) -#define mix(d,s) mx(d,s); mx(d,s); mx(d,s); mx(d,s) -#elif AES_BLOCK_SIZE == 24 -#define cpy(d,s) cp(d,s); cp(d,s); cp(d,s); cp(d,s); \ - cp(d,s); cp(d,s) -#define mix(d,s) mx(d,s); mx(d,s); mx(d,s); mx(d,s); \ - mx(d,s); mx(d,s) -#elif AES_BLOCK_SIZE == 32 -#define cpy(d,s) cp(d,s); cp(d,s); cp(d,s); cp(d,s); \ - cp(d,s); cp(d,s); cp(d,s); cp(d,s) -#define mix(d,s) mx(d,s); mx(d,s); mx(d,s); mx(d,s); \ - mx(d,s); mx(d,s); mx(d,s); mx(d,s) -#else - -#define cpy(d,s) \ -switch(nc) \ -{ case 8: cp(d,s); cp(d,s); \ - case 6: cp(d,s); cp(d,s); \ - case 4: cp(d,s); cp(d,s); \ - cp(d,s); cp(d,s); \ -} - -#define mix(d,s) \ -switch(nc) \ -{ case 8: mx(d,s); mx(d,s); \ - case 6: mx(d,s); mx(d,s); \ - case 4: mx(d,s); mx(d,s); \ - mx(d,s); mx(d,s); \ -} - -#endif - -// y = output word, x = input word, r = row, c = column -// for r = 0, 1, 2 and 3 = column accessed for row r - -#if defined(ARRAYS) -#define s(x,c) x[c] -#else -#define s(x,c) x##c -#endif - -// I am grateful to Frank Yellin for the following constructions -// which, given the column (c) of the output state variable that -// is being computed, return the input state variables which are -// needed for each row (r) of the state - -// For the fixed block size options, compilers reduce these two -// expressions to fixed variable references. For variable block -// size code conditional clauses will sometimes be returned - -#define unused 77 // Sunset Strip - -#define fwd_var(x,r,c) \ - ( r==0 ? \ - ( c==0 ? s(x,0) \ - : c==1 ? s(x,1) \ - : c==2 ? s(x,2) \ - : c==3 ? s(x,3) \ - : c==4 ? s(x,4) \ - : c==5 ? s(x,5) \ - : c==6 ? s(x,6) \ - : s(x,7)) \ - : r==1 ? \ - ( c==0 ? s(x,1) \ - : c==1 ? s(x,2) \ - : c==2 ? s(x,3) \ - : c==3 ? nc==4 ? s(x,0) : s(x,4) \ - : c==4 ? s(x,5) \ - : c==5 ? nc==8 ? s(x,6) : s(x,0) \ - : c==6 ? s(x,7) \ - : s(x,0)) \ - : r==2 ? \ - ( c==0 ? nc==8 ? s(x,3) : s(x,2) \ - : c==1 ? nc==8 ? s(x,4) : s(x,3) \ - : c==2 ? nc==4 ? s(x,0) : nc==8 ? s(x,5) : s(x,4) \ - : c==3 ? nc==4 ? s(x,1) : nc==8 ? s(x,6) : s(x,5) \ - : c==4 ? nc==8 ? s(x,7) : s(x,0) \ - : c==5 ? nc==8 ? s(x,0) : s(x,1) \ - : c==6 ? s(x,1) \ - : s(x,2)) \ - : \ - ( c==0 ? nc==8 ? s(x,4) : s(x,3) \ - : c==1 ? nc==4 ? s(x,0) : nc==8 ? s(x,5) : s(x,4) \ - : c==2 ? nc==4 ? s(x,1) : nc==8 ? s(x,6) : s(x,5) \ - : c==3 ? nc==4 ? s(x,2) : nc==8 ? s(x,7) : s(x,0) \ - : c==4 ? nc==8 ? s(x,0) : s(x,1) \ - : c==5 ? nc==8 ? s(x,1) : s(x,2) \ - : c==6 ? s(x,2) \ - : s(x,3))) - -#define inv_var(x,r,c) \ - ( r==0 ? \ - ( c==0 ? s(x,0) \ - : c==1 ? s(x,1) \ - : c==2 ? s(x,2) \ - : c==3 ? s(x,3) \ - : c==4 ? s(x,4) \ - : c==5 ? s(x,5) \ - : c==6 ? s(x,6) \ - : s(x,7)) \ - : r==1 ? \ - ( c==0 ? nc==4 ? s(x,3) : nc==8 ? s(x,7) : s(x,5) \ - : c==1 ? s(x,0) \ - : c==2 ? s(x,1) \ - : c==3 ? s(x,2) \ - : c==4 ? s(x,3) \ - : c==5 ? s(x,4) \ - : c==6 ? s(x,5) \ - : s(x,6)) \ - : r==2 ? \ - ( c==0 ? nc==4 ? s(x,2) : nc==8 ? s(x,5) : s(x,4) \ - : c==1 ? nc==4 ? s(x,3) : nc==8 ? s(x,6) : s(x,5) \ - : c==2 ? nc==8 ? s(x,7) : s(x,0) \ - : c==3 ? nc==8 ? s(x,0) : s(x,1) \ - : c==4 ? nc==8 ? s(x,1) : s(x,2) \ - : c==5 ? nc==8 ? s(x,2) : s(x,3) \ - : c==6 ? s(x,3) \ - : s(x,4)) \ - : \ - ( c==0 ? nc==4 ? s(x,1) : nc==8 ? s(x,4) : s(x,3) \ - : c==1 ? nc==4 ? s(x,2) : nc==8 ? s(x,5) : s(x,4) \ - : c==2 ? nc==4 ? s(x,3) : nc==8 ? s(x,6) : s(x,5) \ - : c==3 ? nc==8 ? s(x,7) : s(x,0) \ - : c==4 ? nc==8 ? s(x,0) : s(x,1) \ - : c==5 ? nc==8 ? s(x,1) : s(x,2) \ - : c==6 ? s(x,2) \ - : s(x,3))) - -#define si(y,x,k,c) s(y,c) = const_word_in(x + 4 * c) ^ k[c] -#define so(y,x,c) word_out(y + 4 * c, s(x,c)) - -#if defined(FOUR_TABLES) -#define fwd_rnd(y,x,k,c) s(y,c)= (k)[c] ^ four_tables(x,ft_tab,fwd_var,rf1,c) -#define inv_rnd(y,x,k,c) s(y,c)= (k)[c] ^ four_tables(x,it_tab,inv_var,rf1,c) -#elif defined(ONE_TABLE) -#define fwd_rnd(y,x,k,c) s(y,c)= (k)[c] ^ one_table(x,upr,ft_tab,fwd_var,rf1,c) -#define inv_rnd(y,x,k,c) s(y,c)= (k)[c] ^ one_table(x,upr,it_tab,inv_var,rf1,c) -#else -#define fwd_rnd(y,x,k,c) s(y,c) = fwd_mcol(no_table(x,s_box,fwd_var,rf1,c)) ^ (k)[c] -#define inv_rnd(y,x,k,c) s(y,c) = inv_mcol(no_table(x,inv_s_box,inv_var,rf1,c) ^ (k)[c]) -#endif - -#if defined(FOUR_LR_TABLES) -#define fwd_lrnd(y,x,k,c) s(y,c)= (k)[c] ^ four_tables(x,fl_tab,fwd_var,rf1,c) -#define inv_lrnd(y,x,k,c) s(y,c)= (k)[c] ^ four_tables(x,il_tab,inv_var,rf1,c) -#elif defined(ONE_LR_TABLE) -#define fwd_lrnd(y,x,k,c) s(y,c)= (k)[c] ^ one_table(x,ups,fl_tab,fwd_var,rf1,c) -#define inv_lrnd(y,x,k,c) s(y,c)= (k)[c] ^ one_table(x,ups,il_tab,inv_var,rf1,c) -#else -#define fwd_lrnd(y,x,k,c) s(y,c) = no_table(x,s_box,fwd_var,rf1,c) ^ (k)[c] -#define inv_lrnd(y,x,k,c) s(y,c) = no_table(x,inv_s_box,inv_var,rf1,c) ^ (k)[c] -#endif - -#if AES_BLOCK_SIZE == 16 - -#if defined(ARRAYS) -#define locals(y,x) x[4],y[4] -#else -#define locals(y,x) x##0,x##1,x##2,x##3,y##0,y##1,y##2,y##3 -// the following defines prevent the compiler requiring the declaration -// of generated but unused variables in the fwd_var and inv_var macros -#define b04 unused -#define b05 unused -#define b06 unused -#define b07 unused -#define b14 unused -#define b15 unused -#define b16 unused -#define b17 unused -#endif -#define l_copy(y, x) s(y,0) = s(x,0); s(y,1) = s(x,1); \ - s(y,2) = s(x,2); s(y,3) = s(x,3); -#define state_in(y,x,k) si(y,x,k,0); si(y,x,k,1); si(y,x,k,2); si(y,x,k,3) -#define state_out(y,x) so(y,x,0); so(y,x,1); so(y,x,2); so(y,x,3) -#define round(rm,y,x,k) rm(y,x,k,0); rm(y,x,k,1); rm(y,x,k,2); rm(y,x,k,3) - -#elif AES_BLOCK_SIZE == 24 - -#if defined(ARRAYS) -#define locals(y,x) x[6],y[6] -#else -#define locals(y,x) x##0,x##1,x##2,x##3,x##4,x##5, \ - y##0,y##1,y##2,y##3,y##4,y##5 -#define b06 unused -#define b07 unused -#define b16 unused -#define b17 unused -#endif -#define l_copy(y, x) s(y,0) = s(x,0); s(y,1) = s(x,1); \ - s(y,2) = s(x,2); s(y,3) = s(x,3); \ - s(y,4) = s(x,4); s(y,5) = s(x,5); -#define state_in(y,x,k) si(y,x,k,0); si(y,x,k,1); si(y,x,k,2); \ - si(y,x,k,3); si(y,x,k,4); si(y,x,k,5) -#define state_out(y,x) so(y,x,0); so(y,x,1); so(y,x,2); \ - so(y,x,3); so(y,x,4); so(y,x,5) -#define round(rm,y,x,k) rm(y,x,k,0); rm(y,x,k,1); rm(y,x,k,2); \ - rm(y,x,k,3); rm(y,x,k,4); rm(y,x,k,5) -#else - -#if defined(ARRAYS) -#define locals(y,x) x[8],y[8] -#else -#define locals(y,x) x##0,x##1,x##2,x##3,x##4,x##5,x##6,x##7, \ - y##0,y##1,y##2,y##3,y##4,y##5,y##6,y##7 -#endif -#define l_copy(y, x) s(y,0) = s(x,0); s(y,1) = s(x,1); \ - s(y,2) = s(x,2); s(y,3) = s(x,3); \ - s(y,4) = s(x,4); s(y,5) = s(x,5); \ - s(y,6) = s(x,6); s(y,7) = s(x,7); - -#if AES_BLOCK_SIZE == 32 - -#define state_in(y,x,k) si(y,x,k,0); si(y,x,k,1); si(y,x,k,2); si(y,x,k,3); \ - si(y,x,k,4); si(y,x,k,5); si(y,x,k,6); si(y,x,k,7) -#define state_out(y,x) so(y,x,0); so(y,x,1); so(y,x,2); so(y,x,3); \ - so(y,x,4); so(y,x,5); so(y,x,6); so(y,x,7) -#define round(rm,y,x,k) rm(y,x,k,0); rm(y,x,k,1); rm(y,x,k,2); rm(y,x,k,3); \ - rm(y,x,k,4); rm(y,x,k,5); rm(y,x,k,6); rm(y,x,k,7) -#else - -#define state_in(y,x,k) \ -switch(nc) \ -{ case 8: si(y,x,k,7); si(y,x,k,6); \ - case 6: si(y,x,k,5); si(y,x,k,4); \ - case 4: si(y,x,k,3); si(y,x,k,2); \ - si(y,x,k,1); si(y,x,k,0); \ -} - -#define state_out(y,x) \ -switch(nc) \ -{ case 8: so(y,x,7); so(y,x,6); \ - case 6: so(y,x,5); so(y,x,4); \ - case 4: so(y,x,3); so(y,x,2); \ - so(y,x,1); so(y,x,0); \ -} - -#if defined(FAST_VARIABLE) - -#define round(rm,y,x,k) \ -switch(nc) \ -{ case 8: rm(y,x,k,7); rm(y,x,k,6); \ - rm(y,x,k,5); rm(y,x,k,4); \ - rm(y,x,k,3); rm(y,x,k,2); \ - rm(y,x,k,1); rm(y,x,k,0); \ - break; \ - case 6: rm(y,x,k,5); rm(y,x,k,4); \ - rm(y,x,k,3); rm(y,x,k,2); \ - rm(y,x,k,1); rm(y,x,k,0); \ - break; \ - case 4: rm(y,x,k,3); rm(y,x,k,2); \ - rm(y,x,k,1); rm(y,x,k,0); \ - break; \ -} -#else - -#define round(rm,y,x,k) \ -switch(nc) \ -{ case 8: rm(y,x,k,7); rm(y,x,k,6); \ - case 6: rm(y,x,k,5); rm(y,x,k,4); \ - case 4: rm(y,x,k,3); rm(y,x,k,2); \ - rm(y,x,k,1); rm(y,x,k,0); \ -} - -#endif - -#endif -#endif - -/** - * Implementation of private_aes_cbc_crypter_t.encrypt_block. - */ -static void encrypt_block(const private_aes_cbc_crypter_t *this, const unsigned char in_blk[], unsigned char out_blk[]) -{ u_int32_t locals(b0, b1); - const u_int32_t *kp = this->aes_e_key; - -#if !defined(ONE_TABLE) && !defined(FOUR_TABLES) - u_int32_t f2; -#endif - - state_in(b0, in_blk, kp); kp += nc; - -#if defined(UNROLL) - - switch(this->aes_Nrnd) - { - case 14: round(fwd_rnd, b1, b0, kp ); - round(fwd_rnd, b0, b1, kp + nc ); kp += 2 * nc; - case 12: round(fwd_rnd, b1, b0, kp ); - round(fwd_rnd, b0, b1, kp + nc ); kp += 2 * nc; - case 10: round(fwd_rnd, b1, b0, kp ); - round(fwd_rnd, b0, b1, kp + nc); - round(fwd_rnd, b1, b0, kp + 2 * nc); - round(fwd_rnd, b0, b1, kp + 3 * nc); - round(fwd_rnd, b1, b0, kp + 4 * nc); - round(fwd_rnd, b0, b1, kp + 5 * nc); - round(fwd_rnd, b1, b0, kp + 6 * nc); - round(fwd_rnd, b0, b1, kp + 7 * nc); - round(fwd_rnd, b1, b0, kp + 8 * nc); - round(fwd_lrnd, b0, b1, kp + 9 * nc); - } - -#elif defined(PARTIAL_UNROLL) - { u_int32_t rnd; - - for(rnd = 0; rnd < (this->aes_Nrnd >> 1) - 1; ++rnd) - { - round(fwd_rnd, b1, b0, kp); - round(fwd_rnd, b0, b1, kp + nc); kp += 2 * nc; - } - - round(fwd_rnd, b1, b0, kp); - round(fwd_lrnd, b0, b1, kp + nc); - } -#else - { u_int32_t rnd; - - for(rnd = 0; rnd < this->aes_Nrnd - 1; ++rnd) - { - round(fwd_rnd, b1, b0, kp); - l_copy(b0, b1); kp += nc; - } - - round(fwd_lrnd, b0, b1, kp); - } -#endif - - state_out(out_blk, b0); -} - -/** - * Implementation of private_aes_cbc_crypter_t.decrypt_block. - */ -static void decrypt_block(const private_aes_cbc_crypter_t *this, const unsigned char in_blk[], unsigned char out_blk[]) -{ u_int32_t locals(b0, b1); - const u_int32_t *kp = this->aes_d_key; - -#if !defined(ONE_TABLE) && !defined(FOUR_TABLES) - u_int32_t f2, f4, f8, f9; -#endif - - state_in(b0, in_blk, kp); kp += nc; - -#if defined(UNROLL) - - switch(this->aes_Nrnd) - { - case 14: round(inv_rnd, b1, b0, kp ); - round(inv_rnd, b0, b1, kp + nc ); kp += 2 * nc; - case 12: round(inv_rnd, b1, b0, kp ); - round(inv_rnd, b0, b1, kp + nc ); kp += 2 * nc; - case 10: round(inv_rnd, b1, b0, kp ); - round(inv_rnd, b0, b1, kp + nc); - round(inv_rnd, b1, b0, kp + 2 * nc); - round(inv_rnd, b0, b1, kp + 3 * nc); - round(inv_rnd, b1, b0, kp + 4 * nc); - round(inv_rnd, b0, b1, kp + 5 * nc); - round(inv_rnd, b1, b0, kp + 6 * nc); - round(inv_rnd, b0, b1, kp + 7 * nc); - round(inv_rnd, b1, b0, kp + 8 * nc); - round(inv_lrnd, b0, b1, kp + 9 * nc); - } - -#elif defined(PARTIAL_UNROLL) - { u_int32_t rnd; - - for(rnd = 0; rnd < (this->aes_Nrnd >> 1) - 1; ++rnd) - { - round(inv_rnd, b1, b0, kp); - round(inv_rnd, b0, b1, kp + nc); kp += 2 * nc; - } - - round(inv_rnd, b1, b0, kp); - round(inv_lrnd, b0, b1, kp + nc); - } -#else - { u_int32_t rnd; - - for(rnd = 0; rnd < this->aes_Nrnd - 1; ++rnd) - { - round(inv_rnd, b1, b0, kp); - l_copy(b0, b1); kp += nc; - } - - round(inv_lrnd, b0, b1, kp); - } -#endif - - state_out(out_blk, b0); -} - -/** - * Implementation of crypter_t.decrypt. - */ -static status_t decrypt (private_aes_cbc_crypter_t *this, chunk_t data, chunk_t iv, chunk_t *decrypted) -{ - int ret, pos; - const u_int32_t *iv_i; - u_int8_t *in, *out; - - ret = data.len; - if (((data.len) % 16) != 0) - { - /* data length must be padded to a multiple of blocksize */ - return INVALID_ARG; - } - - decrypted->ptr = malloc(data.len); - if (decrypted->ptr == NULL) - { - return OUT_OF_RES; - } - decrypted->len = data.len; - - in = data.ptr; - out = decrypted->ptr; - - pos=data.len-16; - in+=pos; - out+=pos; - while(pos>=0) { - this->decrypt_block(this,in,out); - if (pos==0) - iv_i=(const u_int32_t*) (iv.ptr); - else - iv_i=(const u_int32_t*) (in-16); - *((u_int32_t *)(&out[ 0])) ^= iv_i[0]; - *((u_int32_t *)(&out[ 4])) ^= iv_i[1]; - *((u_int32_t *)(&out[ 8])) ^= iv_i[2]; - *((u_int32_t *)(&out[12])) ^= iv_i[3]; - in-=16; - out-=16; - pos-=16; - } - - return SUCCESS; -} - - -/** - * Implementation of crypter_t.decrypt. - */ -static status_t encrypt (private_aes_cbc_crypter_t *this, chunk_t data, chunk_t iv, chunk_t *encrypted) -{ - int ret, pos; - const u_int32_t *iv_i; - u_int8_t *in, *out; - - ret = data.len; - if (((data.len) % 16) != 0) - { - /* data length must be padded to a multiple of blocksize */ - return INVALID_ARG; - } - - encrypted->ptr = malloc(data.len); - if (encrypted->ptr == NULL) - { - return OUT_OF_RES; - } - encrypted->len = data.len; - - in = data.ptr; - out = encrypted->ptr; - - pos=0; - while(pos<data.len) - { - if (pos==0) - iv_i=(const u_int32_t*) iv.ptr; - else - iv_i=(const u_int32_t*) (out-16); - *((u_int32_t *)(&out[ 0])) = iv_i[0]^*((const u_int32_t *)(&in[ 0])); - *((u_int32_t *)(&out[ 4])) = iv_i[1]^*((const u_int32_t *)(&in[ 4])); - *((u_int32_t *)(&out[ 8])) = iv_i[2]^*((const u_int32_t *)(&in[ 8])); - *((u_int32_t *)(&out[12])) = iv_i[3]^*((const u_int32_t *)(&in[12])); - this->encrypt_block(this,out,out); - in+=16; - out+=16; - pos+=16; - } - return SUCCESS; -} - -/** - * Implementation of crypter_t.get_block_size. - */ -static size_t get_block_size (private_aes_cbc_crypter_t *this) -{ - return AES_BLOCK_SIZE; -} - -/** - * Implementation of crypter_t.get_key_size. - */ -static size_t get_key_size (private_aes_cbc_crypter_t *this) -{ - return this->key_size; -} - -/** - * Implementation of crypter_t.set_key. - */ -static status_t set_key (private_aes_cbc_crypter_t *this, chunk_t key) -{ - u_int32_t *kf, *kt, rci, f = 0; - u_int8_t *in_key = key.ptr; - - if (key.len != this->key_size) - { - return INVALID_ARG; - } - - this->aes_Nrnd = (this->aes_Nkey > (nc) ? this->aes_Nkey : (nc)) + 6; - - this->aes_e_key[0] = const_word_in(in_key ); - this->aes_e_key[1] = const_word_in(in_key + 4); - this->aes_e_key[2] = const_word_in(in_key + 8); - this->aes_e_key[3] = const_word_in(in_key + 12); - - kf = this->aes_e_key; - kt = kf + nc * (this->aes_Nrnd + 1) - this->aes_Nkey; - rci = 0; - - switch(this->aes_Nkey) - { - case 4: do - { kf[4] = kf[0] ^ ls_box(kf[3],3) ^ rcon_tab[rci++]; - kf[5] = kf[1] ^ kf[4]; - kf[6] = kf[2] ^ kf[5]; - kf[7] = kf[3] ^ kf[6]; - kf += 4; - } - while(kf < kt); - break; - - case 6: this->aes_e_key[4] = const_word_in(in_key + 16); - this->aes_e_key[5] = const_word_in(in_key + 20); - do - { kf[ 6] = kf[0] ^ ls_box(kf[5],3) ^ rcon_tab[rci++]; - kf[ 7] = kf[1] ^ kf[ 6]; - kf[ 8] = kf[2] ^ kf[ 7]; - kf[ 9] = kf[3] ^ kf[ 8]; - kf[10] = kf[4] ^ kf[ 9]; - kf[11] = kf[5] ^ kf[10]; - kf += 6; - } - while(kf < kt); - break; - - case 8: this->aes_e_key[4] = const_word_in(in_key + 16); - this->aes_e_key[5] = const_word_in(in_key + 20); - this->aes_e_key[6] = const_word_in(in_key + 24); - this->aes_e_key[7] = const_word_in(in_key + 28); - do - { kf[ 8] = kf[0] ^ ls_box(kf[7],3) ^ rcon_tab[rci++]; - kf[ 9] = kf[1] ^ kf[ 8]; - kf[10] = kf[2] ^ kf[ 9]; - kf[11] = kf[3] ^ kf[10]; - kf[12] = kf[4] ^ ls_box(kf[11],0); - kf[13] = kf[5] ^ kf[12]; - kf[14] = kf[6] ^ kf[13]; - kf[15] = kf[7] ^ kf[14]; - kf += 8; - } - while (kf < kt); - break; - } - - if(!f) - { - u_int32_t i; - - kt = this->aes_d_key + nc * this->aes_Nrnd; - kf = this->aes_e_key; - - cpy(kt, kf); kt -= 2 * nc; - - for(i = 1; i < this->aes_Nrnd; ++i) - { -#if defined(ONE_TABLE) || defined(FOUR_TABLES) -#if !defined(ONE_IM_TABLE) && !defined(FOUR_IM_TABLES) - u_int32_t f2, f4, f8, f9; -#endif - mix(kt, kf); -#else - cpy(kt, kf); -#endif - kt -= 2 * nc; - } - cpy(kt, kf); - } - - return SUCCESS; -} - -/** - * Implementation of crypter_t.destroy and aes_cbc_crypter_t.destroy. - */ -static void destroy (private_aes_cbc_crypter_t *this) -{ - free(this); -} - -/* - * Described in header - */ -aes_cbc_crypter_t *aes_cbc_crypter_create(size_t key_size) -{ - private_aes_cbc_crypter_t *this = malloc_thing(private_aes_cbc_crypter_t); - - #if !defined(FIXED_TABLES) - if(!tab_gen) { gen_tabs(); tab_gen = 1; } - #endif - - this->key_size = key_size; - switch(key_size) { - case 32: /* bytes */ - this->aes_Nkey = 8; - break; - case 24: /* bytes */ - this->aes_Nkey = 6; - break; - case 16: /* bytes */ - this->aes_Nkey = 4; - break; - default: - free(this); - return NULL; - } - - /* functions of crypter_t interface */ - this->public.crypter_interface.encrypt = (status_t (*) (crypter_t *, chunk_t,chunk_t, chunk_t *)) encrypt; - this->public.crypter_interface.decrypt = (status_t (*) (crypter_t *, chunk_t , chunk_t, chunk_t *)) decrypt; - this->public.crypter_interface.get_block_size = (size_t (*) (crypter_t *)) get_block_size; - this->public.crypter_interface.get_key_size = (size_t (*) (crypter_t *)) get_key_size; - this->public.crypter_interface.set_key = (status_t (*) (crypter_t *,chunk_t)) set_key; - this->public.crypter_interface.destroy = (void (*) (crypter_t *)) destroy; - - /* private functions */ - this->decrypt_block = decrypt_block; - this->encrypt_block = encrypt_block; - - return &(this->public); -} diff --git a/src/libstrongswan/crypto/crypters/aes_cbc_crypter.h b/src/libstrongswan/crypto/crypters/aes_cbc_crypter.h deleted file mode 100644 index 5da248b8c..000000000 --- a/src/libstrongswan/crypto/crypters/aes_cbc_crypter.h +++ /dev/null @@ -1,61 +0,0 @@ -/** - * @file aes_cbc_crypter.h - * - * @brief Interface of aes_cbc_crypter_t - * - */ - -/* - * Copyright (C) 2001 Dr B. R. Gladman <brg@gladman.uk.net> - * Copyright (C) 2005-2006 Martin Willi - * Copyright (C) 2005 Jan Hutter - * Hochschule fuer Technik Rapperswil - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -#ifndef AES_CBC_CRYPTER_H_ -#define AES_CBC_CRYPTER_H_ - -typedef struct aes_cbc_crypter_t aes_cbc_crypter_t; - -#include <crypto/crypters/crypter.h> - -/** - * @brief Class implementing the AES symmetric encryption algorithm. - * - * @b Constructors: - * - aes_cbc_crypter_create() - * - * @ingroup crypters - */ -struct aes_cbc_crypter_t { - - /** - * The crypter_t interface. - */ - crypter_t crypter_interface; -}; - -/** - * @brief Constructor to create aes_cbc_crypter_t objects. - * - * Supported key sizes are: 16, 24 or 32. - * - * @param key_size key size in bytes - * @return - * - aes_cbc_crypter_t object - * - NULL if key size not supported - */ -aes_cbc_crypter_t *aes_cbc_crypter_create(size_t key_size); - - -#endif /* AES_CBC_CRYPTER_H_ */ diff --git a/src/libstrongswan/crypto/crypters/crypter.c b/src/libstrongswan/crypto/crypters/crypter.c index 7f62741a7..2c291a9f5 100644 --- a/src/libstrongswan/crypto/crypters/crypter.c +++ b/src/libstrongswan/crypto/crypters/crypter.c @@ -1,10 +1,3 @@ -/** - * @file crypter.c - * - * @brief Generic constructor for crypter_t. - * - */ - /* * Copyright (C) 2005-2006 Martin Willi * Copyright (C) 2005 Jan Hutter @@ -19,15 +12,12 @@ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. + * + * $Id: crypter.c 3971 2008-05-16 13:27:21Z tobias $ */ - #include "crypter.h" -#include <crypto/crypters/aes_cbc_crypter.h> -#include <crypto/crypters/des_crypter.h> - - ENUM_BEGIN(encryption_algorithm_names, ENCR_UNDEFINED, ENCR_UNDEFINED, "UNDEFINED"); ENUM_NEXT(encryption_algorithm_names, ENCR_DES_IV64, ENCR_DES_IV32, ENCR_UNDEFINED, @@ -40,29 +30,16 @@ ENUM_NEXT(encryption_algorithm_names, ENCR_DES_IV64, ENCR_DES_IV32, ENCR_UNDEFIN "BLOWFISH", "3IDEA", "DES_IV32"); -ENUM_NEXT(encryption_algorithm_names, ENCR_NULL, ENCR_AES_CTR, ENCR_DES_IV32, +ENUM_NEXT(encryption_algorithm_names, ENCR_NULL, ENCR_AES_CCM_ICV16, ENCR_DES_IV32, "NULL", "AES_CBC", - "AES_CTR"); -ENUM_END(encryption_algorithm_names, ENCR_AES_CTR); + "AES_CTR", + "AES_CCM_8", + "AES_CCM_12", + "AES_CCM_16"); +ENUM_NEXT(encryption_algorithm_names, ENCR_AES_GCM_ICV8, ENCR_AES_GCM_ICV16, ENCR_AES_CCM_ICV16, + "AES_GCM_8", + "AES_GCM_12", + "AES_GCM_16"); +ENUM_END(encryption_algorithm_names, ENCR_AES_GCM_ICV16); -/* - * Described in header. - */ -crypter_t *crypter_create(encryption_algorithm_t encryption_algorithm, size_t key_size) -{ - switch (encryption_algorithm) - { - case ENCR_AES_CBC: - { - return (crypter_t*)aes_cbc_crypter_create(key_size); - } - case ENCR_DES: - case ENCR_3DES: - { - return (crypter_t*)des_crypter_create(encryption_algorithm); - } - default: - return NULL; - } -} diff --git a/src/libstrongswan/crypto/crypters/crypter.h b/src/libstrongswan/crypto/crypters/crypter.h index 46d94ce93..aade888fa 100644 --- a/src/libstrongswan/crypto/crypters/crypter.h +++ b/src/libstrongswan/crypto/crypters/crypter.h @@ -1,10 +1,3 @@ -/** - * @file crypter.h - * - * @brief Interface crypter_t - * - */ - /* * Copyright (C) 2005-2006 Martin Willi * Copyright (C) 2005 Jan Hutter @@ -19,6 +12,13 @@ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. + * + * $Id: crypter.h 3971 2008-05-16 13:27:21Z tobias $ + */ + +/** + * @defgroup crypter crypter + * @{ @ingroup crypto */ #ifndef CRYPTER_H_ @@ -30,21 +30,12 @@ typedef struct crypter_t crypter_t; #include <library.h> /** - * @brief Encryption algorithm, as in IKEv2 RFC 3.3.2. - * - * Currently only the following algorithms are implemented: - * - ENCR_AES_CBC - * - ENCR_DES - * - ENCR_3DES - * - * @ingroup crypters + * Encryption algorithm, as in IKEv2 RFC 3.3.2. */ enum encryption_algorithm_t { ENCR_UNDEFINED = 1024, ENCR_DES_IV64 = 1, - /** Implemented in class des_crypter_t */ ENCR_DES = 2, - /** Implemented in class des_crypter_t */ ENCR_3DES = 3, ENCR_RC5 = 4, ENCR_IDEA = 5, @@ -53,9 +44,14 @@ enum encryption_algorithm_t { ENCR_3IDEA = 8, ENCR_DES_IV32 = 9, ENCR_NULL = 11, - /** Implemented in class aes_cbc_crypter_t */ ENCR_AES_CBC = 12, - ENCR_AES_CTR = 13 + ENCR_AES_CTR = 13, + ENCR_AES_CCM_ICV8 = 14, + ENCR_AES_CCM_ICV12 = 15, + ENCR_AES_CCM_ICV16 = 16, + ENCR_AES_GCM_ICV8 = 18, + ENCR_AES_GCM_ICV12 = 19, + ENCR_AES_GCM_ICV16 = 20 }; /** @@ -64,92 +60,65 @@ enum encryption_algorithm_t { extern enum_name_t *encryption_algorithm_names; /** - * @brief Generic interface for symmetric encryption algorithms. - * - * @b Constructors: - * - crypter_create() - * - * @ingroup crypters + * Generic interface for symmetric encryption algorithms. */ struct crypter_t { /** - * @brief Encrypt a chunk of data and allocate space for the encrypted value. + * Encrypt a chunk of data and allocate space for the encrypted value. * - * @param this calling object - * @param data data to encrypt - * @param iv initializing vector - * @param[out] encrypted pointer where the encrypted bytes will be written - * @return - * - SUCCESS - * - INVALID_ARG if data size not a multiple of block size + * The length of the iv must equal to get_block_size(), while the length + * of data must be a multiple it. + * If encrypted is NULL, the encryption is done in-place (overwriting data). + * + * @param data data to encrypt + * @param iv initializing vector + * @param encrypted chunk to allocate encrypted data, or NULL */ - status_t (*encrypt) (crypter_t *this, chunk_t data, chunk_t iv, chunk_t *encrypted); + void (*encrypt) (crypter_t *this, chunk_t data, chunk_t iv, + chunk_t *encrypted); /** - * @brief Decrypt a chunk of data and allocate space for the decrypted value. + * Decrypt a chunk of data and allocate space for the decrypted value. + * + * The length of the iv must equal to get_block_size(), while the length + * of data must be a multiple it. + * If decrpyted is NULL, the encryption is done in-place (overwriting data). * - * @param this calling object - * @param data data to decrypt - * @param iv initializing vector - * @param[out] encrypted pointer where the decrypted bytes will be written - * @return - * - SUCCESS - * - INVALID_ARG if data size not a multiple of block size + * @param data data to decrypt + * @param iv initializing vector + * @param encrypted chunk to allocate decrypted data, or NULL */ - status_t (*decrypt) (crypter_t *this, chunk_t data, chunk_t iv, chunk_t *decrypted); + void (*decrypt) (crypter_t *this, chunk_t data, chunk_t iv, + chunk_t *decrypted); /** - * @brief Get the block size of this crypter_t object. + * Get the block size of the crypto algorithm. * - * @param this calling object * @return block size in bytes */ size_t (*get_block_size) (crypter_t *this); /** - * @brief Get the key size of this crypter_t object. + * Get the key size of the crypto algorithm. * - * @param this calling object * @return key size in bytes */ size_t (*get_key_size) (crypter_t *this); /** - * @brief Set the key for this crypter_t object. - * - * @param this calling object + * Set the key. + * + * The length of the key must match get_key_size(). + * * @param key key to set - * @return - * - SUCCESS - * - INVALID_ARG if key length invalid */ - status_t (*set_key) (crypter_t *this, chunk_t key); + void (*set_key) (crypter_t *this, chunk_t key); /** - * @brief Destroys a crypter_t object. - * - * @param this calling object + * Destroys a crypter_t object. */ void (*destroy) (crypter_t *this); }; -/** - * @brief Generic constructor for crypter_t objects. - * - * Currently only the following algorithms are implemented: - * - ENCR_AES_CBC - * - ENCR_DES - * - ENCR_3DES - * - * The key_size is ignored for algorithms with fixed key size. - * - * @param encryption_algorithm Algorithm to use for crypter - * @param key_size size of the key in bytes - * @return - * - crypter_t object - * - NULL if encryption algorithm/key_size is not supported - */ -crypter_t *crypter_create(encryption_algorithm_t encryption_algorithm, size_t key_size); - -#endif /*CRYPTER_H_*/ +#endif /*CRYPTER_H_ @} */ diff --git a/src/libstrongswan/crypto/crypters/des_crypter.c b/src/libstrongswan/crypto/crypters/des_crypter.c deleted file mode 100644 index 655cc03ce..000000000 --- a/src/libstrongswan/crypto/crypters/des_crypter.c +++ /dev/null @@ -1,1536 +0,0 @@ -/** - * @file des_crypter.c - * - * @brief Implementation of des_crypter_t - * - */ - -/* Copyright (C) 2006 Martin Willi - * Hochschule fuer Technik Rapperswil - * - * Derived from Plutos DES library by Eric Young. - * - * Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) - * All rights reserved. - * - * This package is an SSL implementation written - * by Eric Young (eay@cryptsoft.com). - * The implementation was written so as to conform with Netscapes SSL. - * - * This library is free for commercial and non-commercial use as long as - * the following conditions are aheared to. - * - * Copyright remains Eric Young's, and as such any Copyright notices in - * the code are not to be removed. - * If this package is used in a product, Eric Young should be given attribution - * as the author of the parts of the library used. - * This can be in the form of a textual message at program startup or - * in documentation (online or textual) provided with the package. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * "This product includes cryptographic software written by - * Eric Young (eay@cryptsoft.com)" - * The word 'cryptographic' can be left out if the rouines from the library - * being used are not cryptographic related :-). - * 4. If you include any Windows specific code (or a derivative thereof) from - * the apps directory (application code) you must include an acknowledgement: - * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" - * - * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * The licence and distribution terms for any publically available version or - * derivative of this code cannot be changed. i.e. this code cannot simply be - * copied and put under another distribution licence - * [including the GNU Public Licence.] - */ - -#include "des_crypter.h" - -typedef u_char des_cblock[8]; - -typedef struct des_ks_struct { - des_cblock _; -} des_key_schedule[16]; - - -typedef struct private_des_crypter_t private_des_crypter_t; - -/** - * Private data for des_crypter_t - */ -struct private_des_crypter_t { - - /** - * Public part of this class. - */ - des_crypter_t public; - - /** - * Key size, depends on algoritm... - */ - size_t key_size; - - union { - /** key schedule for single des */ - des_key_schedule ks; - /** key schedule for 3des */ - des_key_schedule ks3[3]; - }; -}; - - -#define DES_ENCRYPT 1 -#define DES_DECRYPT 0 - -#define DES_LONG u_int32_t - -#if defined(WIN32) || defined(WIN16) -#ifndef MSDOS -#define MSDOS -#endif -#endif - -#ifndef DES_DEFAULT_OPTIONS -/* the following is tweaked from a config script, that is why it is a - * protected undef/define */ -#ifndef DES_PTR -#define DES_PTR -#endif - -/* This helps C compiler generate the correct code for multiple functional - * units. It reduces register dependancies at the expense of 2 more - * registers */ -#ifndef DES_RISC1 -#define DES_RISC1 -#endif - -#ifndef DES_RISC2 -#undef DES_RISC2 -#endif - -#if defined(DES_RISC1) && defined(DES_RISC2) -YOU SHOULD NOT HAVE BOTH DES_RISC1 AND DES_RISC2 DEFINED!!!!! -#endif - -/* Unroll the inner loop, this sometimes helps, sometimes hinders. - * Very mucy CPU dependant */ -#ifndef DES_UNROLL -#define DES_UNROLL -#endif - -/* These default values were supplied by - * Peter Gutman <pgut001@cs.auckland.ac.nz> - * They are only used if nothing else has been defined */ -#if !defined(DES_PTR) && !defined(DES_RISC1) && !defined(DES_RISC2) && !defined(DES_UNROLL) -/* Special defines which change the way the code is built depending on the - CPU and OS. For SGI machines you can use _MIPS_SZLONG (32 or 64) to find - even newer MIPS CPU's, but at the moment one size fits all for - optimization options. Older Sparc's work better with only UNROLL, but - there's no way to tell at compile time what it is you're running on */ - -#if defined( sun ) /* Newer Sparc's */ -#define DES_PTR -#define DES_RISC1 -#define DES_UNROLL -#elif defined( __ultrix ) /* Older MIPS */ -#define DES_PTR -#define DES_RISC2 -#define DES_UNROLL -#elif defined( __osf1__ ) /* Alpha */ -#define DES_PTR -#define DES_RISC2 -#elif defined ( _AIX ) /* RS6000 */ - /* Unknown */ -#elif defined( __hpux ) /* HP-PA */ - /* Unknown */ -#elif defined( __aux ) /* 68K */ - /* Unknown */ -#elif defined( __dgux ) /* 88K (but P6 in latest boxes) */ -#define DES_UNROLL -#elif defined( __sgi ) /* Newer MIPS */ -#define DES_PTR -#define DES_RISC2 -#define DES_UNROLL -#elif defined( i386 ) /* x86 boxes, should be gcc */ -#define DES_PTR -#define DES_RISC1 -#define DES_UNROLL -#endif /* Systems-specific speed defines */ -#endif - -#endif /* DES_DEFAULT_OPTIONS */ - -#ifdef MSDOS /* Visual C++ 2.1 (Windows NT/95) */ -#include <stdlib.h> -#include <errno.h> -#include <time.h> -#include <io.h> -#ifndef RAND -#define RAND -#endif -#undef NOPROTO -#endif - -#if defined(__STDC__) || defined(VMS) || defined(M_XENIX) || defined(MSDOS) -#ifndef __KERNEL__ -#include <string.h> -#else -#include <linux/string.h> -#endif -#endif - -#ifndef RAND -#define RAND -#endif - -#ifdef linux -#undef RAND -#endif - -#ifdef MSDOS -#define getpid() 2 -#define RAND -#undef NOPROTO -#endif - -#if defined(NOCONST) -#define const -#endif - -#ifdef __STDC__ -#undef NOPROTO -#endif - -#ifdef RAND -#define srandom(s) srand(s) -#define random rand -#endif - -#define ITERATIONS 16 -#define HALF_ITERATIONS 8 - -/* used in des_read and des_write */ -#define MAXWRITE (1024*16) -#define BSIZE (MAXWRITE+4) - -#define c2l(c,l) (l =((DES_LONG)(*((c)++))) , \ - l|=((DES_LONG)(*((c)++)))<< 8L, \ - l|=((DES_LONG)(*((c)++)))<<16L, \ - l|=((DES_LONG)(*((c)++)))<<24L) - -/* NOTE - c is not incremented as per c2l */ -#define c2ln(c,l1,l2,n) { \ - c+=n; \ - l1=l2=0; \ - switch (n) { \ - case 8: l2 =((DES_LONG)(*(--(c))))<<24L; \ - case 7: l2|=((DES_LONG)(*(--(c))))<<16L; \ - case 6: l2|=((DES_LONG)(*(--(c))))<< 8L; \ - case 5: l2|=((DES_LONG)(*(--(c)))); \ - case 4: l1 =((DES_LONG)(*(--(c))))<<24L; \ - case 3: l1|=((DES_LONG)(*(--(c))))<<16L; \ - case 2: l1|=((DES_LONG)(*(--(c))))<< 8L; \ - case 1: l1|=((DES_LONG)(*(--(c)))); \ -} \ -} - -#define l2c(l,c) (*((c)++)=(unsigned char)(((l) )&0xff), \ - *((c)++)=(unsigned char)(((l)>> 8L)&0xff), \ - *((c)++)=(unsigned char)(((l)>>16L)&0xff), \ - *((c)++)=(unsigned char)(((l)>>24L)&0xff)) - -/* replacements for htonl and ntohl since I have no idea what to do - * when faced with machines with 8 byte longs. */ -#define HDRSIZE 4 - -#define n2l(c,l) (l =((DES_LONG)(*((c)++)))<<24L, \ - l|=((DES_LONG)(*((c)++)))<<16L, \ - l|=((DES_LONG)(*((c)++)))<< 8L, \ - l|=((DES_LONG)(*((c)++)))) - -#define l2n(l,c) (*((c)++)=(unsigned char)(((l)>>24L)&0xff), \ - *((c)++)=(unsigned char)(((l)>>16L)&0xff), \ - *((c)++)=(unsigned char)(((l)>> 8L)&0xff), \ - *((c)++)=(unsigned char)(((l) )&0xff)) - -/* NOTE - c is not incremented as per l2c */ -#define l2cn(l1,l2,c,n) { \ - c+=n; \ - switch (n) { \ - case 8: *(--(c))=(unsigned char)(((l2)>>24L)&0xff); \ - case 7: *(--(c))=(unsigned char)(((l2)>>16L)&0xff); \ - case 6: *(--(c))=(unsigned char)(((l2)>> 8L)&0xff); \ - case 5: *(--(c))=(unsigned char)(((l2) )&0xff); \ - case 4: *(--(c))=(unsigned char)(((l1)>>24L)&0xff); \ - case 3: *(--(c))=(unsigned char)(((l1)>>16L)&0xff); \ - case 2: *(--(c))=(unsigned char)(((l1)>> 8L)&0xff); \ - case 1: *(--(c))=(unsigned char)(((l1) )&0xff); \ -} \ -} - -#if defined(WIN32) -#define ROTATE(a,n) (_lrotr(a,n)) -#else -#define ROTATE(a,n) (((a)>>(n))+((a)<<(32-(n)))) -#endif - -/* Don't worry about the LOAD_DATA() stuff, that is used by - * fcrypt() to add it's little bit to the front */ - -#ifdef DES_FCRYPT - -#define LOAD_DATA_tmp(R,S,u,t,E0,E1) \ -{ DES_LONG tmp; LOAD_DATA(R,S,u,t,E0,E1,tmp); } - -#define LOAD_DATA(R,S,u,t,E0,E1,tmp) \ - t=R^(R>>16L); \ - u=t&E0; t&=E1; \ - tmp=(u<<16); u^=R^s[S ]; u^=tmp; \ - tmp=(t<<16); t^=R^s[S+1]; t^=tmp -#else -#define LOAD_DATA_tmp(a,b,c,d,e,f) LOAD_DATA(a,b,c,d,e,f,g) -#define LOAD_DATA(R,S,u,t,E0,E1,tmp) \ - u=R^s[S ]; \ - t=R^s[S+1] -#endif - -/* The changes to this macro may help or hinder, depending on the - * compiler and the achitecture. gcc2 always seems to do well :-). - * Inspired by Dana How <how@isl.stanford.edu> - * DO NOT use the alternative version on machines with 8 byte longs. - * It does not seem to work on the Alpha, even when DES_LONG is 4 - * bytes, probably an issue of accessing non-word aligned objects :-( */ -#ifdef DES_PTR - -/* It recently occured to me that 0^0^0^0^0^0^0 == 0, so there - * is no reason to not xor all the sub items together. This potentially - * saves a register since things can be xored directly into L */ - -#if defined(DES_RISC1) || defined(DES_RISC2) -#ifdef DES_RISC1 -#define D_ENCRYPT(LL,R,S) { \ - unsigned int u1,u2,u3; \ - LOAD_DATA(R,S,u,t,E0,E1,u1); \ - u2=(int)u>>8L; \ - u1=(int)u&0xfc; \ - u2&=0xfc; \ - t=ROTATE(t,4); \ - u>>=16L; \ - LL^= *(DES_LONG *)((unsigned char *)des_SP +u1); \ - LL^= *(DES_LONG *)((unsigned char *)des_SP+0x200+u2); \ - u3=(int)(u>>8L); \ - u1=(int)u&0xfc; \ - u3&=0xfc; \ - LL^= *(DES_LONG *)((unsigned char *)des_SP+0x400+u1); \ - LL^= *(DES_LONG *)((unsigned char *)des_SP+0x600+u3); \ - u2=(int)t>>8L; \ - u1=(int)t&0xfc; \ - u2&=0xfc; \ - t>>=16L; \ - LL^= *(DES_LONG *)((unsigned char *)des_SP+0x100+u1); \ - LL^= *(DES_LONG *)((unsigned char *)des_SP+0x300+u2); \ - u3=(int)t>>8L; \ - u1=(int)t&0xfc; \ - u3&=0xfc; \ - LL^= *(DES_LONG *)((unsigned char *)des_SP+0x500+u1); \ - LL^= *(DES_LONG *)((unsigned char *)des_SP+0x700+u3); } -#endif -#ifdef DES_RISC2 -#define D_ENCRYPT(LL,R,S) { \ - unsigned int u1,u2,s1,s2; \ - LOAD_DATA(R,S,u,t,E0,E1,u1); \ - u2=(int)u>>8L; \ - u1=(int)u&0xfc; \ - u2&=0xfc; \ - t=ROTATE(t,4); \ - LL^= *(DES_LONG *)((unsigned char *)des_SP +u1); \ - LL^= *(DES_LONG *)((unsigned char *)des_SP+0x200+u2); \ - s1=(int)(u>>16L); \ - s2=(int)(u>>24L); \ - s1&=0xfc; \ - s2&=0xfc; \ - LL^= *(DES_LONG *)((unsigned char *)des_SP+0x400+s1); \ - LL^= *(DES_LONG *)((unsigned char *)des_SP+0x600+s2); \ - u2=(int)t>>8L; \ - u1=(int)t&0xfc; \ - u2&=0xfc; \ - LL^= *(DES_LONG *)((unsigned char *)des_SP+0x100+u1); \ - LL^= *(DES_LONG *)((unsigned char *)des_SP+0x300+u2); \ - s1=(int)(t>>16L); \ - s2=(int)(t>>24L); \ - s1&=0xfc; \ - s2&=0xfc; \ - LL^= *(DES_LONG *)((unsigned char *)des_SP+0x500+s1); \ - LL^= *(DES_LONG *)((unsigned char *)des_SP+0x700+s2); } -#endif -#else -#define D_ENCRYPT(LL,R,S) { \ - LOAD_DATA_tmp(R,S,u,t,E0,E1); \ - t=ROTATE(t,4); \ - LL^= \ - *(DES_LONG *)((unsigned char *)des_SP +((u )&0xfc))^ \ - *(DES_LONG *)((unsigned char *)des_SP+0x200+((u>> 8L)&0xfc))^ \ - *(DES_LONG *)((unsigned char *)des_SP+0x400+((u>>16L)&0xfc))^ \ - *(DES_LONG *)((unsigned char *)des_SP+0x600+((u>>24L)&0xfc))^ \ - *(DES_LONG *)((unsigned char *)des_SP+0x100+((t )&0xfc))^ \ - *(DES_LONG *)((unsigned char *)des_SP+0x300+((t>> 8L)&0xfc))^ \ - *(DES_LONG *)((unsigned char *)des_SP+0x500+((t>>16L)&0xfc))^ \ - *(DES_LONG *)((unsigned char *)des_SP+0x700+((t>>24L)&0xfc)); } -#endif - -#else /* original version */ - -#if defined(DES_RISC1) || defined(DES_RISC2) -#ifdef DES_RISC1 -#define D_ENCRYPT(LL,R,S) {\ - unsigned int u1,u2,u3; \ - LOAD_DATA(R,S,u,t,E0,E1,u1); \ - u>>=2L; \ - t=ROTATE(t,6); \ - u2=(int)u>>8L; \ - u1=(int)u&0x3f; \ - u2&=0x3f; \ - u>>=16L; \ - LL^=des_SPtrans[0][u1]; \ - LL^=des_SPtrans[2][u2]; \ - u3=(int)u>>8L; \ - u1=(int)u&0x3f; \ - u3&=0x3f; \ - LL^=des_SPtrans[4][u1]; \ - LL^=des_SPtrans[6][u3]; \ - u2=(int)t>>8L; \ - u1=(int)t&0x3f; \ - u2&=0x3f; \ - t>>=16L; \ - LL^=des_SPtrans[1][u1]; \ - LL^=des_SPtrans[3][u2]; \ - u3=(int)t>>8L; \ - u1=(int)t&0x3f; \ - u3&=0x3f; \ - LL^=des_SPtrans[5][u1]; \ - LL^=des_SPtrans[7][u3]; } -#endif -#ifdef DES_RISC2 -#define D_ENCRYPT(LL,R,S) {\ - unsigned int u1,u2,s1,s2; \ - LOAD_DATA(R,S,u,t,E0,E1,u1); \ - u>>=2L; \ - t=ROTATE(t,6); \ - u2=(int)u>>8L; \ - u1=(int)u&0x3f; \ - u2&=0x3f; \ - LL^=des_SPtrans[0][u1]; \ - LL^=des_SPtrans[2][u2]; \ - s1=(int)u>>16L; \ - s2=(int)u>>24L; \ - s1&=0x3f; \ - s2&=0x3f; \ - LL^=des_SPtrans[4][s1]; \ - LL^=des_SPtrans[6][s2]; \ - u2=(int)t>>8L; \ - u1=(int)t&0x3f; \ - u2&=0x3f; \ - LL^=des_SPtrans[1][u1]; \ - LL^=des_SPtrans[3][u2]; \ - s1=(int)t>>16; \ - s2=(int)t>>24L; \ - s1&=0x3f; \ - s2&=0x3f; \ - LL^=des_SPtrans[5][s1]; \ - LL^=des_SPtrans[7][s2]; } -#endif - -#else - -#define D_ENCRYPT(LL,R,S) {\ - LOAD_DATA_tmp(R,S,u,t,E0,E1); \ - t=ROTATE(t,4); \ - LL^=\ - des_SPtrans[0][(u>> 2L)&0x3f]^ \ - des_SPtrans[2][(u>>10L)&0x3f]^ \ - des_SPtrans[4][(u>>18L)&0x3f]^ \ - des_SPtrans[6][(u>>26L)&0x3f]^ \ - des_SPtrans[1][(t>> 2L)&0x3f]^ \ - des_SPtrans[3][(t>>10L)&0x3f]^ \ - des_SPtrans[5][(t>>18L)&0x3f]^ \ - des_SPtrans[7][(t>>26L)&0x3f]; } -#endif -#endif - - /* IP and FP - * The problem is more of a geometric problem that random bit fiddling. - 0 1 2 3 4 5 6 7 62 54 46 38 30 22 14 6 - 8 9 10 11 12 13 14 15 60 52 44 36 28 20 12 4 - 16 17 18 19 20 21 22 23 58 50 42 34 26 18 10 2 - 24 25 26 27 28 29 30 31 to 56 48 40 32 24 16 8 0 - - 32 33 34 35 36 37 38 39 63 55 47 39 31 23 15 7 - 40 41 42 43 44 45 46 47 61 53 45 37 29 21 13 5 - 48 49 50 51 52 53 54 55 59 51 43 35 27 19 11 3 - 56 57 58 59 60 61 62 63 57 49 41 33 25 17 9 1 - - The output has been subject to swaps of the form - 0 1 -> 3 1 but the odd and even bits have been put into - 2 3 2 0 - different words. The main trick is to remember that - t=((l>>size)^r)&(mask); - r^=t; - l^=(t<<size); - can be used to swap and move bits between words. - - So l = 0 1 2 3 r = 16 17 18 19 - 4 5 6 7 20 21 22 23 - 8 9 10 11 24 25 26 27 - 12 13 14 15 28 29 30 31 - becomes (for size == 2 and mask == 0x3333) - t = 2^16 3^17 -- -- l = 0 1 16 17 r = 2 3 18 19 - 6^20 7^21 -- -- 4 5 20 21 6 7 22 23 - 10^24 11^25 -- -- 8 9 24 25 10 11 24 25 - 14^28 15^29 -- -- 12 13 28 29 14 15 28 29 - - Thanks for hints from Richard Outerbridge - he told me IP&FP - could be done in 15 xor, 10 shifts and 5 ands. - When I finally started to think of the problem in 2D - I first got ~42 operations without xors. When I remembered - how to use xors :-) I got it to its final state. - */ -#define PERM_OP(a,b,t,n,m) ((t)=((((a)>>(n))^(b))&(m)),\ - (b)^=(t),\ - (a)^=((t)<<(n))) - -#define IP(l,r) \ -{ \ - register DES_LONG tt; \ - PERM_OP(r,l,tt, 4,0x0f0f0f0fL); \ - PERM_OP(l,r,tt,16,0x0000ffffL); \ - PERM_OP(r,l,tt, 2,0x33333333L); \ - PERM_OP(l,r,tt, 8,0x00ff00ffL); \ - PERM_OP(r,l,tt, 1,0x55555555L); \ -} - -#define FP(l,r) \ -{ \ - register DES_LONG tt; \ - PERM_OP(l,r,tt, 1,0x55555555L); \ - PERM_OP(r,l,tt, 8,0x00ff00ffL); \ - PERM_OP(l,r,tt, 2,0x33333333L); \ - PERM_OP(r,l,tt,16,0x0000ffffL); \ - PERM_OP(l,r,tt, 4,0x0f0f0f0fL); \ -} - -#ifndef NOPROTO -void fcrypt_body(DES_LONG *out,des_key_schedule ks, - DES_LONG Eswap0, DES_LONG Eswap1); -#else -void fcrypt_body(); -#endif - -static const DES_LONG des_skb[8][64]={ - { /* for C bits (numbered as per FIPS 46) 1 2 3 4 5 6 */ - 0x00000000L,0x00000010L,0x20000000L,0x20000010L, - 0x00010000L,0x00010010L,0x20010000L,0x20010010L, - 0x00000800L,0x00000810L,0x20000800L,0x20000810L, - 0x00010800L,0x00010810L,0x20010800L,0x20010810L, - 0x00000020L,0x00000030L,0x20000020L,0x20000030L, - 0x00010020L,0x00010030L,0x20010020L,0x20010030L, - 0x00000820L,0x00000830L,0x20000820L,0x20000830L, - 0x00010820L,0x00010830L,0x20010820L,0x20010830L, - 0x00080000L,0x00080010L,0x20080000L,0x20080010L, - 0x00090000L,0x00090010L,0x20090000L,0x20090010L, - 0x00080800L,0x00080810L,0x20080800L,0x20080810L, - 0x00090800L,0x00090810L,0x20090800L,0x20090810L, - 0x00080020L,0x00080030L,0x20080020L,0x20080030L, - 0x00090020L,0x00090030L,0x20090020L,0x20090030L, - 0x00080820L,0x00080830L,0x20080820L,0x20080830L, - 0x00090820L,0x00090830L,0x20090820L,0x20090830L, - }, - { /* for C bits (numbered as per FIPS 46) 7 8 10 11 12 13 */ - 0x00000000L,0x02000000L,0x00002000L,0x02002000L, - 0x00200000L,0x02200000L,0x00202000L,0x02202000L, - 0x00000004L,0x02000004L,0x00002004L,0x02002004L, - 0x00200004L,0x02200004L,0x00202004L,0x02202004L, - 0x00000400L,0x02000400L,0x00002400L,0x02002400L, - 0x00200400L,0x02200400L,0x00202400L,0x02202400L, - 0x00000404L,0x02000404L,0x00002404L,0x02002404L, - 0x00200404L,0x02200404L,0x00202404L,0x02202404L, - 0x10000000L,0x12000000L,0x10002000L,0x12002000L, - 0x10200000L,0x12200000L,0x10202000L,0x12202000L, - 0x10000004L,0x12000004L,0x10002004L,0x12002004L, - 0x10200004L,0x12200004L,0x10202004L,0x12202004L, - 0x10000400L,0x12000400L,0x10002400L,0x12002400L, - 0x10200400L,0x12200400L,0x10202400L,0x12202400L, - 0x10000404L,0x12000404L,0x10002404L,0x12002404L, - 0x10200404L,0x12200404L,0x10202404L,0x12202404L, - }, - { /* for C bits (numbered as per FIPS 46) 14 15 16 17 19 20 */ - 0x00000000L,0x00000001L,0x00040000L,0x00040001L, - 0x01000000L,0x01000001L,0x01040000L,0x01040001L, - 0x00000002L,0x00000003L,0x00040002L,0x00040003L, - 0x01000002L,0x01000003L,0x01040002L,0x01040003L, - 0x00000200L,0x00000201L,0x00040200L,0x00040201L, - 0x01000200L,0x01000201L,0x01040200L,0x01040201L, - 0x00000202L,0x00000203L,0x00040202L,0x00040203L, - 0x01000202L,0x01000203L,0x01040202L,0x01040203L, - 0x08000000L,0x08000001L,0x08040000L,0x08040001L, - 0x09000000L,0x09000001L,0x09040000L,0x09040001L, - 0x08000002L,0x08000003L,0x08040002L,0x08040003L, - 0x09000002L,0x09000003L,0x09040002L,0x09040003L, - 0x08000200L,0x08000201L,0x08040200L,0x08040201L, - 0x09000200L,0x09000201L,0x09040200L,0x09040201L, - 0x08000202L,0x08000203L,0x08040202L,0x08040203L, - 0x09000202L,0x09000203L,0x09040202L,0x09040203L, - }, - { /* for C bits (numbered as per FIPS 46) 21 23 24 26 27 28 */ - 0x00000000L,0x00100000L,0x00000100L,0x00100100L, - 0x00000008L,0x00100008L,0x00000108L,0x00100108L, - 0x00001000L,0x00101000L,0x00001100L,0x00101100L, - 0x00001008L,0x00101008L,0x00001108L,0x00101108L, - 0x04000000L,0x04100000L,0x04000100L,0x04100100L, - 0x04000008L,0x04100008L,0x04000108L,0x04100108L, - 0x04001000L,0x04101000L,0x04001100L,0x04101100L, - 0x04001008L,0x04101008L,0x04001108L,0x04101108L, - 0x00020000L,0x00120000L,0x00020100L,0x00120100L, - 0x00020008L,0x00120008L,0x00020108L,0x00120108L, - 0x00021000L,0x00121000L,0x00021100L,0x00121100L, - 0x00021008L,0x00121008L,0x00021108L,0x00121108L, - 0x04020000L,0x04120000L,0x04020100L,0x04120100L, - 0x04020008L,0x04120008L,0x04020108L,0x04120108L, - 0x04021000L,0x04121000L,0x04021100L,0x04121100L, - 0x04021008L,0x04121008L,0x04021108L,0x04121108L, - }, - { /* for D bits (numbered as per FIPS 46) 1 2 3 4 5 6 */ - 0x00000000L,0x10000000L,0x00010000L,0x10010000L, - 0x00000004L,0x10000004L,0x00010004L,0x10010004L, - 0x20000000L,0x30000000L,0x20010000L,0x30010000L, - 0x20000004L,0x30000004L,0x20010004L,0x30010004L, - 0x00100000L,0x10100000L,0x00110000L,0x10110000L, - 0x00100004L,0x10100004L,0x00110004L,0x10110004L, - 0x20100000L,0x30100000L,0x20110000L,0x30110000L, - 0x20100004L,0x30100004L,0x20110004L,0x30110004L, - 0x00001000L,0x10001000L,0x00011000L,0x10011000L, - 0x00001004L,0x10001004L,0x00011004L,0x10011004L, - 0x20001000L,0x30001000L,0x20011000L,0x30011000L, - 0x20001004L,0x30001004L,0x20011004L,0x30011004L, - 0x00101000L,0x10101000L,0x00111000L,0x10111000L, - 0x00101004L,0x10101004L,0x00111004L,0x10111004L, - 0x20101000L,0x30101000L,0x20111000L,0x30111000L, - 0x20101004L,0x30101004L,0x20111004L,0x30111004L, - }, - { /* for D bits (numbered as per FIPS 46) 8 9 11 12 13 14 */ - 0x00000000L,0x08000000L,0x00000008L,0x08000008L, - 0x00000400L,0x08000400L,0x00000408L,0x08000408L, - 0x00020000L,0x08020000L,0x00020008L,0x08020008L, - 0x00020400L,0x08020400L,0x00020408L,0x08020408L, - 0x00000001L,0x08000001L,0x00000009L,0x08000009L, - 0x00000401L,0x08000401L,0x00000409L,0x08000409L, - 0x00020001L,0x08020001L,0x00020009L,0x08020009L, - 0x00020401L,0x08020401L,0x00020409L,0x08020409L, - 0x02000000L,0x0A000000L,0x02000008L,0x0A000008L, - 0x02000400L,0x0A000400L,0x02000408L,0x0A000408L, - 0x02020000L,0x0A020000L,0x02020008L,0x0A020008L, - 0x02020400L,0x0A020400L,0x02020408L,0x0A020408L, - 0x02000001L,0x0A000001L,0x02000009L,0x0A000009L, - 0x02000401L,0x0A000401L,0x02000409L,0x0A000409L, - 0x02020001L,0x0A020001L,0x02020009L,0x0A020009L, - 0x02020401L,0x0A020401L,0x02020409L,0x0A020409L, - }, - { /* for D bits (numbered as per FIPS 46) 16 17 18 19 20 21 */ - 0x00000000L,0x00000100L,0x00080000L,0x00080100L, - 0x01000000L,0x01000100L,0x01080000L,0x01080100L, - 0x00000010L,0x00000110L,0x00080010L,0x00080110L, - 0x01000010L,0x01000110L,0x01080010L,0x01080110L, - 0x00200000L,0x00200100L,0x00280000L,0x00280100L, - 0x01200000L,0x01200100L,0x01280000L,0x01280100L, - 0x00200010L,0x00200110L,0x00280010L,0x00280110L, - 0x01200010L,0x01200110L,0x01280010L,0x01280110L, - 0x00000200L,0x00000300L,0x00080200L,0x00080300L, - 0x01000200L,0x01000300L,0x01080200L,0x01080300L, - 0x00000210L,0x00000310L,0x00080210L,0x00080310L, - 0x01000210L,0x01000310L,0x01080210L,0x01080310L, - 0x00200200L,0x00200300L,0x00280200L,0x00280300L, - 0x01200200L,0x01200300L,0x01280200L,0x01280300L, - 0x00200210L,0x00200310L,0x00280210L,0x00280310L, - 0x01200210L,0x01200310L,0x01280210L,0x01280310L, - }, - { /* for D bits (numbered as per FIPS 46) 22 23 24 25 27 28 */ - 0x00000000L,0x04000000L,0x00040000L,0x04040000L, - 0x00000002L,0x04000002L,0x00040002L,0x04040002L, - 0x00002000L,0x04002000L,0x00042000L,0x04042000L, - 0x00002002L,0x04002002L,0x00042002L,0x04042002L, - 0x00000020L,0x04000020L,0x00040020L,0x04040020L, - 0x00000022L,0x04000022L,0x00040022L,0x04040022L, - 0x00002020L,0x04002020L,0x00042020L,0x04042020L, - 0x00002022L,0x04002022L,0x00042022L,0x04042022L, - 0x00000800L,0x04000800L,0x00040800L,0x04040800L, - 0x00000802L,0x04000802L,0x00040802L,0x04040802L, - 0x00002800L,0x04002800L,0x00042800L,0x04042800L, - 0x00002802L,0x04002802L,0x00042802L,0x04042802L, - 0x00000820L,0x04000820L,0x00040820L,0x04040820L, - 0x00000822L,0x04000822L,0x00040822L,0x04040822L, - 0x00002820L,0x04002820L,0x00042820L,0x04042820L, - 0x00002822L,0x04002822L,0x00042822L,0x04042822L, - } -}; - -const DES_LONG des_SPtrans[8][64]={ - { - /* nibble 0 */ - 0x02080800L, 0x00080000L, 0x02000002L, 0x02080802L, - 0x02000000L, 0x00080802L, 0x00080002L, 0x02000002L, - 0x00080802L, 0x02080800L, 0x02080000L, 0x00000802L, - 0x02000802L, 0x02000000L, 0x00000000L, 0x00080002L, - 0x00080000L, 0x00000002L, 0x02000800L, 0x00080800L, - 0x02080802L, 0x02080000L, 0x00000802L, 0x02000800L, - 0x00000002L, 0x00000800L, 0x00080800L, 0x02080002L, - 0x00000800L, 0x02000802L, 0x02080002L, 0x00000000L, - 0x00000000L, 0x02080802L, 0x02000800L, 0x00080002L, - 0x02080800L, 0x00080000L, 0x00000802L, 0x02000800L, - 0x02080002L, 0x00000800L, 0x00080800L, 0x02000002L, - 0x00080802L, 0x00000002L, 0x02000002L, 0x02080000L, - 0x02080802L, 0x00080800L, 0x02080000L, 0x02000802L, - 0x02000000L, 0x00000802L, 0x00080002L, 0x00000000L, - 0x00080000L, 0x02000000L, 0x02000802L, 0x02080800L, - 0x00000002L, 0x02080002L, 0x00000800L, 0x00080802L, - }, - { /* nibble 1 */ - 0x40108010L, 0x00000000L, 0x00108000L, 0x40100000L, - 0x40000010L, 0x00008010L, 0x40008000L, 0x00108000L, - 0x00008000L, 0x40100010L, 0x00000010L, 0x40008000L, - 0x00100010L, 0x40108000L, 0x40100000L, 0x00000010L, - 0x00100000L, 0x40008010L, 0x40100010L, 0x00008000L, - 0x00108010L, 0x40000000L, 0x00000000L, 0x00100010L, - 0x40008010L, 0x00108010L, 0x40108000L, 0x40000010L, - 0x40000000L, 0x00100000L, 0x00008010L, 0x40108010L, - 0x00100010L, 0x40108000L, 0x40008000L, 0x00108010L, - 0x40108010L, 0x00100010L, 0x40000010L, 0x00000000L, - 0x40000000L, 0x00008010L, 0x00100000L, 0x40100010L, - 0x00008000L, 0x40000000L, 0x00108010L, 0x40008010L, - 0x40108000L, 0x00008000L, 0x00000000L, 0x40000010L, - 0x00000010L, 0x40108010L, 0x00108000L, 0x40100000L, - 0x40100010L, 0x00100000L, 0x00008010L, 0x40008000L, - 0x40008010L, 0x00000010L, 0x40100000L, 0x00108000L, - }, - { /* nibble 2 */ - 0x04000001L, 0x04040100L, 0x00000100L, 0x04000101L, - 0x00040001L, 0x04000000L, 0x04000101L, 0x00040100L, - 0x04000100L, 0x00040000L, 0x04040000L, 0x00000001L, - 0x04040101L, 0x00000101L, 0x00000001L, 0x04040001L, - 0x00000000L, 0x00040001L, 0x04040100L, 0x00000100L, - 0x00000101L, 0x04040101L, 0x00040000L, 0x04000001L, - 0x04040001L, 0x04000100L, 0x00040101L, 0x04040000L, - 0x00040100L, 0x00000000L, 0x04000000L, 0x00040101L, - 0x04040100L, 0x00000100L, 0x00000001L, 0x00040000L, - 0x00000101L, 0x00040001L, 0x04040000L, 0x04000101L, - 0x00000000L, 0x04040100L, 0x00040100L, 0x04040001L, - 0x00040001L, 0x04000000L, 0x04040101L, 0x00000001L, - 0x00040101L, 0x04000001L, 0x04000000L, 0x04040101L, - 0x00040000L, 0x04000100L, 0x04000101L, 0x00040100L, - 0x04000100L, 0x00000000L, 0x04040001L, 0x00000101L, - 0x04000001L, 0x00040101L, 0x00000100L, 0x04040000L, - }, - { /* nibble 3 */ - 0x00401008L, 0x10001000L, 0x00000008L, 0x10401008L, - 0x00000000L, 0x10400000L, 0x10001008L, 0x00400008L, - 0x10401000L, 0x10000008L, 0x10000000L, 0x00001008L, - 0x10000008L, 0x00401008L, 0x00400000L, 0x10000000L, - 0x10400008L, 0x00401000L, 0x00001000L, 0x00000008L, - 0x00401000L, 0x10001008L, 0x10400000L, 0x00001000L, - 0x00001008L, 0x00000000L, 0x00400008L, 0x10401000L, - 0x10001000L, 0x10400008L, 0x10401008L, 0x00400000L, - 0x10400008L, 0x00001008L, 0x00400000L, 0x10000008L, - 0x00401000L, 0x10001000L, 0x00000008L, 0x10400000L, - 0x10001008L, 0x00000000L, 0x00001000L, 0x00400008L, - 0x00000000L, 0x10400008L, 0x10401000L, 0x00001000L, - 0x10000000L, 0x10401008L, 0x00401008L, 0x00400000L, - 0x10401008L, 0x00000008L, 0x10001000L, 0x00401008L, - 0x00400008L, 0x00401000L, 0x10400000L, 0x10001008L, - 0x00001008L, 0x10000000L, 0x10000008L, 0x10401000L, - }, - { /* nibble 4 */ - 0x08000000L, 0x00010000L, 0x00000400L, 0x08010420L, - 0x08010020L, 0x08000400L, 0x00010420L, 0x08010000L, - 0x00010000L, 0x00000020L, 0x08000020L, 0x00010400L, - 0x08000420L, 0x08010020L, 0x08010400L, 0x00000000L, - 0x00010400L, 0x08000000L, 0x00010020L, 0x00000420L, - 0x08000400L, 0x00010420L, 0x00000000L, 0x08000020L, - 0x00000020L, 0x08000420L, 0x08010420L, 0x00010020L, - 0x08010000L, 0x00000400L, 0x00000420L, 0x08010400L, - 0x08010400L, 0x08000420L, 0x00010020L, 0x08010000L, - 0x00010000L, 0x00000020L, 0x08000020L, 0x08000400L, - 0x08000000L, 0x00010400L, 0x08010420L, 0x00000000L, - 0x00010420L, 0x08000000L, 0x00000400L, 0x00010020L, - 0x08000420L, 0x00000400L, 0x00000000L, 0x08010420L, - 0x08010020L, 0x08010400L, 0x00000420L, 0x00010000L, - 0x00010400L, 0x08010020L, 0x08000400L, 0x00000420L, - 0x00000020L, 0x00010420L, 0x08010000L, 0x08000020L, - }, - { /* nibble 5 */ - 0x80000040L, 0x00200040L, 0x00000000L, 0x80202000L, - 0x00200040L, 0x00002000L, 0x80002040L, 0x00200000L, - 0x00002040L, 0x80202040L, 0x00202000L, 0x80000000L, - 0x80002000L, 0x80000040L, 0x80200000L, 0x00202040L, - 0x00200000L, 0x80002040L, 0x80200040L, 0x00000000L, - 0x00002000L, 0x00000040L, 0x80202000L, 0x80200040L, - 0x80202040L, 0x80200000L, 0x80000000L, 0x00002040L, - 0x00000040L, 0x00202000L, 0x00202040L, 0x80002000L, - 0x00002040L, 0x80000000L, 0x80002000L, 0x00202040L, - 0x80202000L, 0x00200040L, 0x00000000L, 0x80002000L, - 0x80000000L, 0x00002000L, 0x80200040L, 0x00200000L, - 0x00200040L, 0x80202040L, 0x00202000L, 0x00000040L, - 0x80202040L, 0x00202000L, 0x00200000L, 0x80002040L, - 0x80000040L, 0x80200000L, 0x00202040L, 0x00000000L, - 0x00002000L, 0x80000040L, 0x80002040L, 0x80202000L, - 0x80200000L, 0x00002040L, 0x00000040L, 0x80200040L, - }, - { /* nibble 6 */ - 0x00004000L, 0x00000200L, 0x01000200L, 0x01000004L, - 0x01004204L, 0x00004004L, 0x00004200L, 0x00000000L, - 0x01000000L, 0x01000204L, 0x00000204L, 0x01004000L, - 0x00000004L, 0x01004200L, 0x01004000L, 0x00000204L, - 0x01000204L, 0x00004000L, 0x00004004L, 0x01004204L, - 0x00000000L, 0x01000200L, 0x01000004L, 0x00004200L, - 0x01004004L, 0x00004204L, 0x01004200L, 0x00000004L, - 0x00004204L, 0x01004004L, 0x00000200L, 0x01000000L, - 0x00004204L, 0x01004000L, 0x01004004L, 0x00000204L, - 0x00004000L, 0x00000200L, 0x01000000L, 0x01004004L, - 0x01000204L, 0x00004204L, 0x00004200L, 0x00000000L, - 0x00000200L, 0x01000004L, 0x00000004L, 0x01000200L, - 0x00000000L, 0x01000204L, 0x01000200L, 0x00004200L, - 0x00000204L, 0x00004000L, 0x01004204L, 0x01000000L, - 0x01004200L, 0x00000004L, 0x00004004L, 0x01004204L, - 0x01000004L, 0x01004200L, 0x01004000L, 0x00004004L, - }, - { /* nibble 7 */ - 0x20800080L, 0x20820000L, 0x00020080L, 0x00000000L, - 0x20020000L, 0x00800080L, 0x20800000L, 0x20820080L, - 0x00000080L, 0x20000000L, 0x00820000L, 0x00020080L, - 0x00820080L, 0x20020080L, 0x20000080L, 0x20800000L, - 0x00020000L, 0x00820080L, 0x00800080L, 0x20020000L, - 0x20820080L, 0x20000080L, 0x00000000L, 0x00820000L, - 0x20000000L, 0x00800000L, 0x20020080L, 0x20800080L, - 0x00800000L, 0x00020000L, 0x20820000L, 0x00000080L, - 0x00800000L, 0x00020000L, 0x20000080L, 0x20820080L, - 0x00020080L, 0x20000000L, 0x00000000L, 0x00820000L, - 0x20800080L, 0x20020080L, 0x20020000L, 0x00800080L, - 0x20820000L, 0x00000080L, 0x00800080L, 0x20020000L, - 0x20820080L, 0x00800000L, 0x20800000L, 0x20000080L, - 0x00820000L, 0x00020080L, 0x20020080L, 0x20800000L, - 0x00000080L, 0x20820000L, 0x00820080L, 0x00000000L, - 0x20000000L, 0x20800080L, 0x00020000L, 0x00820080L, - } -}; - -#define HPERM_OP(a,t,n,m) ((t)=((((a)<<(16-(n)))^(a))&(m)),\ - (a)=(a)^(t)^(t>>(16-(n)))) - -static const unsigned char odd_parity[256]={ - 1, 1, 2, 2, 4, 4, 7, 7, 8, 8, 11, 11, 13, 13, 14, 14, - 16, 16, 19, 19, 21, 21, 22, 22, 25, 25, 26, 26, 28, 28, 31, 31, - 32, 32, 35, 35, 37, 37, 38, 38, 41, 41, 42, 42, 44, 44, 47, 47, - 49, 49, 50, 50, 52, 52, 55, 55, 56, 56, 59, 59, 61, 61, 62, 62, - 64, 64, 67, 67, 69, 69, 70, 70, 73, 73, 74, 74, 76, 76, 79, 79, - 81, 81, 82, 82, 84, 84, 87, 87, 88, 88, 91, 91, 93, 93, 94, 94, - 97, 97, 98, 98,100,100,103,103,104,104,107,107,109,109,110,110, - 112,112,115,115,117,117,118,118,121,121,122,122,124,124,127,127, - 128,128,131,131,133,133,134,134,137,137,138,138,140,140,143,143, - 145,145,146,146,148,148,151,151,152,152,155,155,157,157,158,158, - 161,161,162,162,164,164,167,167,168,168,171,171,173,173,174,174, - 176,176,179,179,181,181,182,182,185,185,186,186,188,188,191,191, - 193,193,194,194,196,196,199,199,200,200,203,203,205,205,206,206, - 208,208,211,211,213,213,214,214,217,217,218,218,220,220,223,223, - 224,224,227,227,229,229,230,230,233,233,234,234,236,236,239,239, - 241,241,242,242,244,244,247,247,248,248,251,251,253,253,254,254 -}; - -/** - * Create key schedule for a single DES 64Bit key - */ -static int des_set_key(des_cblock *key, des_key_schedule *schedule) -{ - static int shifts2[16] = {0,0,1,1,1,1,1,1,0,1,1,1,1,1,1,0}; - register DES_LONG c,d,t,s,t2; - register unsigned char *in; - register DES_LONG *k; - register int i; - des_cblock odd; - - for (i = 0; i < sizeof(des_cblock); i++) - { - odd[i] = odd_parity[(*key)[i]]; - } - - k=(DES_LONG *)schedule; - in=(unsigned char *)&odd; - - c2l(in,c); - c2l(in,d); - - /* do PC1 in 60 simple operations */ -/* PERM_OP(d,c,t,4,0x0f0f0f0fL); - HPERM_OP(c,t,-2, 0xcccc0000L); - HPERM_OP(c,t,-1, 0xaaaa0000L); - HPERM_OP(c,t, 8, 0x00ff0000L); - HPERM_OP(c,t,-1, 0xaaaa0000L); - HPERM_OP(d,t,-8, 0xff000000L); - HPERM_OP(d,t, 8, 0x00ff0000L); - HPERM_OP(d,t, 2, 0x33330000L); - d=((d&0x00aa00aaL)<<7L)|((d&0x55005500L)>>7L)|(d&0xaa55aa55L); - d=(d>>8)|((c&0xf0000000L)>>4); - c&=0x0fffffffL; */ - - /* I now do it in 47 simple operations :-) - * Thanks to John Fletcher (john_fletcher@lccmail.ocf.llnl.gov) - * for the inspiration. :-) */ - PERM_OP (d,c,t,4,0x0f0f0f0fL); - HPERM_OP(c,t,-2,0xcccc0000L); - HPERM_OP(d,t,-2,0xcccc0000L); - PERM_OP (d,c,t,1,0x55555555L); - PERM_OP (c,d,t,8,0x00ff00ffL); - PERM_OP (d,c,t,1,0x55555555L); - d= (((d&0x000000ffL)<<16L)| (d&0x0000ff00L) | - ((d&0x00ff0000L)>>16L)|((c&0xf0000000L)>>4L)); - c&=0x0fffffffL; - - for (i=0; i<ITERATIONS; i++) - { - if (shifts2[i]) - { c=((c>>2L)|(c<<26L)); d=((d>>2L)|(d<<26L)); } - else - { c=((c>>1L)|(c<<27L)); d=((d>>1L)|(d<<27L)); } - c&=0x0fffffffL; - d&=0x0fffffffL; - /* could be a few less shifts but I am to lazy at this - * point in time to investigate */ - s= des_skb[0][ (c )&0x3f ]| - des_skb[1][((c>> 6)&0x03)|((c>> 7L)&0x3c)]| - des_skb[2][((c>>13)&0x0f)|((c>>14L)&0x30)]| - des_skb[3][((c>>20)&0x01)|((c>>21L)&0x06) | - ((c>>22L)&0x38)]; - t= des_skb[4][ (d )&0x3f ]| - des_skb[5][((d>> 7L)&0x03)|((d>> 8L)&0x3c)]| - des_skb[6][ (d>>15L)&0x3f ]| - des_skb[7][((d>>21L)&0x0f)|((d>>22L)&0x30)]; - - /* table contained 0213 4657 */ - t2=((t<<16L)|(s&0x0000ffffL))&0xffffffffL; - *(k++)=ROTATE(t2,30)&0xffffffffL; - - t2=((s>>16L)|(t&0xffff0000L)); - *(k++)=ROTATE(t2,26)&0xffffffffL; - } - return(0); -} - - -static void des_encrypt(DES_LONG *data, des_key_schedule ks, int enc) -{ - register DES_LONG l,r,t,u; -#ifdef DES_PTR - register unsigned char *des_SP=(unsigned char *)des_SPtrans; -#endif -#ifndef DES_UNROLL - register int i; -#endif - register DES_LONG *s; - - r=data[0]; - l=data[1]; - - IP(r,l); - /* Things have been modified so that the initial rotate is - * done outside the loop. This required the - * des_SPtrans values in sp.h to be rotated 1 bit to the right. - * One perl script later and things have a 5% speed up on a sparc2. - * Thanks to Richard Outerbridge <71755.204@CompuServe.COM> - * for pointing this out. */ - /* clear the top bits on machines with 8byte longs */ - /* shift left by 2 */ - r=ROTATE(r,29)&0xffffffffL; - l=ROTATE(l,29)&0xffffffffL; - - s=(DES_LONG *)ks; - /* I don't know if it is worth the effort of loop unrolling the - * inner loop */ - if (enc) - { -#ifdef DES_UNROLL - D_ENCRYPT(l,r, 0); /* 1 */ - D_ENCRYPT(r,l, 2); /* 2 */ - D_ENCRYPT(l,r, 4); /* 3 */ - D_ENCRYPT(r,l, 6); /* 4 */ - D_ENCRYPT(l,r, 8); /* 5 */ - D_ENCRYPT(r,l,10); /* 6 */ - D_ENCRYPT(l,r,12); /* 7 */ - D_ENCRYPT(r,l,14); /* 8 */ - D_ENCRYPT(l,r,16); /* 9 */ - D_ENCRYPT(r,l,18); /* 10 */ - D_ENCRYPT(l,r,20); /* 11 */ - D_ENCRYPT(r,l,22); /* 12 */ - D_ENCRYPT(l,r,24); /* 13 */ - D_ENCRYPT(r,l,26); /* 14 */ - D_ENCRYPT(l,r,28); /* 15 */ - D_ENCRYPT(r,l,30); /* 16 */ -#else - for (i=0; i<32; i+=8) -{ - D_ENCRYPT(l,r,i+0); /* 1 */ - D_ENCRYPT(r,l,i+2); /* 2 */ - D_ENCRYPT(l,r,i+4); /* 3 */ - D_ENCRYPT(r,l,i+6); /* 4 */ -} -#endif - } - else -{ -#ifdef DES_UNROLL - D_ENCRYPT(l,r,30); /* 16 */ - D_ENCRYPT(r,l,28); /* 15 */ - D_ENCRYPT(l,r,26); /* 14 */ - D_ENCRYPT(r,l,24); /* 13 */ - D_ENCRYPT(l,r,22); /* 12 */ - D_ENCRYPT(r,l,20); /* 11 */ - D_ENCRYPT(l,r,18); /* 10 */ - D_ENCRYPT(r,l,16); /* 9 */ - D_ENCRYPT(l,r,14); /* 8 */ - D_ENCRYPT(r,l,12); /* 7 */ - D_ENCRYPT(l,r,10); /* 6 */ - D_ENCRYPT(r,l, 8); /* 5 */ - D_ENCRYPT(l,r, 6); /* 4 */ - D_ENCRYPT(r,l, 4); /* 3 */ - D_ENCRYPT(l,r, 2); /* 2 */ - D_ENCRYPT(r,l, 0); /* 1 */ -#else - for (i=30; i>0; i-=8) -{ - D_ENCRYPT(l,r,i-0); /* 16 */ - D_ENCRYPT(r,l,i-2); /* 15 */ - D_ENCRYPT(l,r,i-4); /* 14 */ - D_ENCRYPT(r,l,i-6); /* 13 */ -} -#endif -} - - /* rotate and clear the top bits on machines with 8byte longs */ - l=ROTATE(l,3)&0xffffffffL; - r=ROTATE(r,3)&0xffffffffL; - - FP(r,l); - data[0]=l; - data[1]=r; - l=r=t=u=0; -} - -/** - * DES CBC encrypt decrypt routine - */ -static void des_cbc_encrypt(des_cblock *input, des_cblock *output, long length, - des_key_schedule schedule, des_cblock *ivec, int enc) -{ - register DES_LONG tin0,tin1; - register DES_LONG tout0,tout1,xor0,xor1; - register unsigned char *in,*out; - register long l=length; - DES_LONG tin[2]; - unsigned char *iv; - - in=(unsigned char *)input; - out=(unsigned char *)output; - iv=(unsigned char *)ivec; - - if (enc) - { - c2l(iv,tout0); - c2l(iv,tout1); - for (l-=8; l>=0; l-=8) - { - c2l(in,tin0); - c2l(in,tin1); - tin0^=tout0; tin[0]=tin0; - tin1^=tout1; tin[1]=tin1; - des_encrypt((DES_LONG *)tin,schedule,DES_ENCRYPT); - tout0=tin[0]; l2c(tout0,out); - tout1=tin[1]; l2c(tout1,out); - } - if (l != -8) - { - c2ln(in,tin0,tin1,l+8); - tin0^=tout0; tin[0]=tin0; - tin1^=tout1; tin[1]=tin1; - des_encrypt((DES_LONG *)tin,schedule,DES_ENCRYPT); - tout0=tin[0]; l2c(tout0,out); - tout1=tin[1]; l2c(tout1,out); - } - } - else - { - c2l(iv,xor0); - c2l(iv,xor1); - for (l-=8; l>=0; l-=8) - { - c2l(in,tin0); tin[0]=tin0; - c2l(in,tin1); tin[1]=tin1; - des_encrypt((DES_LONG *)tin,schedule,DES_DECRYPT); - tout0=tin[0]^xor0; - tout1=tin[1]^xor1; - l2c(tout0,out); - l2c(tout1,out); - xor0=tin0; - xor1=tin1; - } - if (l != -8) - { - c2l(in,tin0); tin[0]=tin0; - c2l(in,tin1); tin[1]=tin1; - des_encrypt((DES_LONG *)tin,schedule,DES_DECRYPT); - tout0=tin[0]^xor0; - tout1=tin[1]^xor1; - l2cn(tout0,tout1,out,l+8); - /* xor0=tin0; - xor1=tin1; */ - } - } - tin0=tin1=tout0=tout1=xor0=xor1=0; - tin[0]=tin[1]=0; -} - -static void des_encrypt2(DES_LONG *data, des_key_schedule ks, int enc) -{ - register DES_LONG l,r,t,u; -#ifdef DES_PTR - register unsigned char *des_SP=(unsigned char *)des_SPtrans; -#endif -#ifndef DES_UNROLL - register int i; -#endif - register DES_LONG *s; - - r=data[0]; - l=data[1]; - - /* Things have been modified so that the initial rotate is - * done outside the loop. This required the - * des_SPtrans values in sp.h to be rotated 1 bit to the right. - * One perl script later and things have a 5% speed up on a sparc2. - * Thanks to Richard Outerbridge <71755.204@CompuServe.COM> - * for pointing this out. - * clear the top bits on machines with 8byte longs */ - r=ROTATE(r,29)&0xffffffffL; - l=ROTATE(l,29)&0xffffffffL; - - s=(DES_LONG *)ks; - /* I don't know if it is worth the effort of loop unrolling the - * inner loop */ - if (enc) - { -#ifdef DES_UNROLL - D_ENCRYPT(l,r, 0); /* 1 */ - D_ENCRYPT(r,l, 2); /* 2 */ - D_ENCRYPT(l,r, 4); /* 3 */ - D_ENCRYPT(r,l, 6); /* 4 */ - D_ENCRYPT(l,r, 8); /* 5 */ - D_ENCRYPT(r,l,10); /* 6 */ - D_ENCRYPT(l,r,12); /* 7 */ - D_ENCRYPT(r,l,14); /* 8 */ - D_ENCRYPT(l,r,16); /* 9 */ - D_ENCRYPT(r,l,18); /* 10 */ - D_ENCRYPT(l,r,20); /* 11 */ - D_ENCRYPT(r,l,22); /* 12 */ - D_ENCRYPT(l,r,24); /* 13 */ - D_ENCRYPT(r,l,26); /* 14 */ - D_ENCRYPT(l,r,28); /* 15 */ - D_ENCRYPT(r,l,30); /* 16 */ -#else - for (i=0; i<32; i+=8) -{ - D_ENCRYPT(l,r,i+0); /* 1 */ - D_ENCRYPT(r,l,i+2); /* 2 */ - D_ENCRYPT(l,r,i+4); /* 3 */ - D_ENCRYPT(r,l,i+6); /* 4 */ -} -#endif - } - else -{ -#ifdef DES_UNROLL - D_ENCRYPT(l,r,30); /* 16 */ - D_ENCRYPT(r,l,28); /* 15 */ - D_ENCRYPT(l,r,26); /* 14 */ - D_ENCRYPT(r,l,24); /* 13 */ - D_ENCRYPT(l,r,22); /* 12 */ - D_ENCRYPT(r,l,20); /* 11 */ - D_ENCRYPT(l,r,18); /* 10 */ - D_ENCRYPT(r,l,16); /* 9 */ - D_ENCRYPT(l,r,14); /* 8 */ - D_ENCRYPT(r,l,12); /* 7 */ - D_ENCRYPT(l,r,10); /* 6 */ - D_ENCRYPT(r,l, 8); /* 5 */ - D_ENCRYPT(l,r, 6); /* 4 */ - D_ENCRYPT(r,l, 4); /* 3 */ - D_ENCRYPT(l,r, 2); /* 2 */ - D_ENCRYPT(r,l, 0); /* 1 */ -#else - for (i=30; i>0; i-=8) -{ - D_ENCRYPT(l,r,i-0); /* 16 */ - D_ENCRYPT(r,l,i-2); /* 15 */ - D_ENCRYPT(l,r,i-4); /* 14 */ - D_ENCRYPT(r,l,i-6); /* 13 */ -} -#endif -} - /* rotate and clear the top bits on machines with 8byte longs */ - data[0]=ROTATE(l,3)&0xffffffffL; - data[1]=ROTATE(r,3)&0xffffffffL; - l=r=t=u=0; -} - -/** - * Single block 3DES EDE encrypt routine - */ -static void des_encrypt3(DES_LONG *data, des_key_schedule ks1, - des_key_schedule ks2, des_key_schedule ks3) -{ - register DES_LONG l,r; - - l=data[0]; - r=data[1]; - IP(l,r); - data[0]=l; - data[1]=r; - des_encrypt2((DES_LONG *)data,ks1,DES_ENCRYPT); - des_encrypt2((DES_LONG *)data,ks2,DES_DECRYPT); - des_encrypt2((DES_LONG *)data,ks3,DES_ENCRYPT); - l=data[0]; - r=data[1]; - FP(r,l); - data[0]=l; - data[1]=r; -} - -/** - * Single block 3DES EDE decrypt routine - */ -static void des_decrypt3(DES_LONG *data, des_key_schedule ks1, - des_key_schedule ks2, des_key_schedule ks3) -{ - register DES_LONG l,r; - - l=data[0]; - r=data[1]; - IP(l,r); - data[0]=l; - data[1]=r; - des_encrypt2((DES_LONG *)data,ks3,DES_DECRYPT); - des_encrypt2((DES_LONG *)data,ks2,DES_ENCRYPT); - des_encrypt2((DES_LONG *)data,ks1,DES_DECRYPT); - l=data[0]; - r=data[1]; - FP(r,l); - data[0]=l; - data[1]=r; -} - -/** - * 3DES EDE CBC encrypt/decrypt routine - */ -static void des_ede3_cbc_encrypt(des_cblock *input, des_cblock *output, long length, - des_key_schedule ks1, des_key_schedule ks2, - des_key_schedule ks3, des_cblock *ivec, int enc) -{ - register DES_LONG tin0,tin1; - register DES_LONG tout0,tout1,xor0,xor1; - register unsigned char *in,*out; - register long l=length; - DES_LONG tin[2]; - unsigned char *iv; - - in=(unsigned char *)input; - out=(unsigned char *)output; - iv=(unsigned char *)ivec; - - if (enc) - { - c2l(iv,tout0); - c2l(iv,tout1); - for (l-=8; l>=0; l-=8) - { - c2l(in,tin0); - c2l(in,tin1); - tin0^=tout0; - tin1^=tout1; - - tin[0]=tin0; - tin[1]=tin1; - des_encrypt3((DES_LONG *)tin,ks1,ks2,ks3); - tout0=tin[0]; - tout1=tin[1]; - - l2c(tout0,out); - l2c(tout1,out); - } - if (l != -8) - { - c2ln(in,tin0,tin1,l+8); - tin0^=tout0; - tin1^=tout1; - - tin[0]=tin0; - tin[1]=tin1; - des_encrypt3((DES_LONG *)tin,ks1,ks2,ks3); - tout0=tin[0]; - tout1=tin[1]; - - l2c(tout0,out); - l2c(tout1,out); - } - iv=(unsigned char *)ivec; - l2c(tout0,iv); - l2c(tout1,iv); - } - else - { - register DES_LONG t0,t1; - - c2l(iv,xor0); - c2l(iv,xor1); - for (l-=8; l>=0; l-=8) - { - c2l(in,tin0); - c2l(in,tin1); - - t0=tin0; - t1=tin1; - - tin[0]=tin0; - tin[1]=tin1; - des_decrypt3((DES_LONG *)tin,ks1,ks2,ks3); - tout0=tin[0]; - tout1=tin[1]; - - tout0^=xor0; - tout1^=xor1; - l2c(tout0,out); - l2c(tout1,out); - xor0=t0; - xor1=t1; - } - if (l != -8) - { - c2l(in,tin0); - c2l(in,tin1); - - t0=tin0; - t1=tin1; - - tin[0]=tin0; - tin[1]=tin1; - des_decrypt3((DES_LONG *)tin,ks1,ks2,ks3); - tout0=tin[0]; - tout1=tin[1]; - - tout0^=xor0; - tout1^=xor1; - l2cn(tout0,tout1,out,l+8); - xor0=t0; - xor1=t1; - } - - iv=(unsigned char *)ivec; - l2c(xor0,iv); - l2c(xor1,iv); - } - tin0=tin1=tout0=tout1=xor0=xor1=0; - tin[0]=tin[1]=0; -} - -/** - * Implementation of crypter_t.decrypt for DES. - */ -static status_t decrypt(private_des_crypter_t *this, chunk_t data, chunk_t iv, chunk_t *decrypted) -{ - des_cblock ivb; - - if (data.len % sizeof(des_cblock) != 0 || - iv.len != sizeof(des_cblock)) - { - return INVALID_ARG; - } - - *decrypted = chunk_alloc(data.len); - memcpy(&ivb, iv.ptr, sizeof(des_cblock)); - des_cbc_encrypt((des_cblock*)(data.ptr), (des_cblock*)(decrypted->ptr), - data.len, this->ks, &ivb, DES_DECRYPT); - return SUCCESS; -} - - -/** - * Implementation of crypter_t.decrypt for DES. - */ -static status_t encrypt(private_des_crypter_t *this, chunk_t data, chunk_t iv, chunk_t *encrypted) -{ - des_cblock ivb; - - if (data.len % sizeof(des_cblock) != 0 || - iv.len != sizeof(des_cblock)) - { - return INVALID_ARG; - } - - *encrypted = chunk_alloc(data.len); - memcpy(&ivb, iv.ptr, sizeof(des_cblock)); - des_cbc_encrypt((des_cblock*)(data.ptr), (des_cblock*)(encrypted->ptr), - data.len, this->ks, &ivb, DES_ENCRYPT); - return SUCCESS; -} - -/** - * Implementation of crypter_t.decrypt for 3DES. - */ -static status_t decrypt3(private_des_crypter_t *this, chunk_t data, chunk_t iv, chunk_t *decrypted) -{ - des_cblock ivb; - - if (data.len % sizeof(des_cblock) != 0 || - iv.len != sizeof(des_cblock)) - { - return INVALID_ARG; - } - - *decrypted = chunk_alloc(data.len); - memcpy(&ivb, iv.ptr, sizeof(des_cblock)); - des_ede3_cbc_encrypt((des_cblock*)(data.ptr), (des_cblock*)(decrypted->ptr), - data.len, this->ks3[0], this->ks3[1], this->ks3[2], - &ivb, DES_DECRYPT); - return SUCCESS; -} - -/** - * Implementation of crypter_t.decrypt for 3DES. - */ -static status_t encrypt3(private_des_crypter_t *this, chunk_t data, chunk_t iv, chunk_t *encrypted) -{ - des_cblock ivb; - - if (data.len % sizeof(des_cblock) != 0 || - iv.len != sizeof(des_cblock)) - { - return INVALID_ARG; - } - - *encrypted = chunk_alloc(data.len); - memcpy(&ivb, iv.ptr, sizeof(des_cblock)); - des_ede3_cbc_encrypt((des_cblock*)(data.ptr), (des_cblock*)(encrypted->ptr), - data.len, this->ks3[0], this->ks3[1], this->ks3[2], - &ivb, DES_ENCRYPT); - return SUCCESS; -} - -/** - * Implementation of crypter_t.get_block_size. - */ -static size_t get_block_size (private_des_crypter_t *this) -{ - return sizeof(des_cblock); -} - -/** - * Implementation of crypter_t.get_key_size. - */ -static size_t get_key_size (private_des_crypter_t *this) -{ - return this->key_size; -} - -/** - * Implementation of crypter_t.set_key for DES. - */ -static status_t set_key(private_des_crypter_t *this, chunk_t key) -{ - if (key.len != sizeof(des_cblock)) - { - return INVALID_ARG; - } - - des_set_key((des_cblock*)(key.ptr), &this->ks); - - return SUCCESS; -} - -/** - * Implementation of crypter_t.set_key for 3DES. - */ -static status_t set_key3(private_des_crypter_t *this, chunk_t key) -{ - if (key.len != 3 * sizeof(des_cblock)) - { - return INVALID_ARG; - } - - des_set_key((des_cblock*)(key.ptr) + 0, &this->ks3[0]); - des_set_key((des_cblock*)(key.ptr) + 1, &this->ks3[1]); - des_set_key((des_cblock*)(key.ptr) + 2, &this->ks3[2]); - - return SUCCESS; -} - -/** - * Implementation of crypter_t.destroy and des_crypter_t.destroy. - */ -static void destroy(private_des_crypter_t *this) -{ - free(this); -} - -/* - * Described in header - */ -des_crypter_t *des_crypter_create(encryption_algorithm_t algo) -{ - private_des_crypter_t *this = malloc_thing(private_des_crypter_t); - - /* functions of crypter_t interface */ - this->public.crypter_interface.get_block_size = (size_t (*) (crypter_t *)) get_block_size; - this->public.crypter_interface.get_key_size = (size_t (*) (crypter_t *)) get_key_size; - this->public.crypter_interface.destroy = (void (*) (crypter_t *)) destroy; - - /* use functions depending on algorithm */ - switch (algo) - { - case ENCR_DES: - this->key_size = sizeof(des_cblock); - this->public.crypter_interface.set_key = (status_t (*) (crypter_t *,chunk_t)) set_key; - this->public.crypter_interface.encrypt = (status_t (*) (crypter_t *, chunk_t,chunk_t, chunk_t *)) encrypt; - this->public.crypter_interface.decrypt = (status_t (*) (crypter_t *, chunk_t , chunk_t, chunk_t *)) decrypt; - break; - case ENCR_3DES: - this->key_size = 3 * sizeof(des_cblock); - this->public.crypter_interface.set_key = (status_t (*) (crypter_t *,chunk_t)) set_key3; - this->public.crypter_interface.encrypt = (status_t (*) (crypter_t *, chunk_t,chunk_t, chunk_t *)) encrypt3; - this->public.crypter_interface.decrypt = (status_t (*) (crypter_t *, chunk_t , chunk_t, chunk_t *)) decrypt3; - break; - default: - free(this); - return NULL; - } - return &(this->public); -} diff --git a/src/libstrongswan/crypto/crypters/des_crypter.h b/src/libstrongswan/crypto/crypters/des_crypter.h deleted file mode 100644 index 0c87b0a9c..000000000 --- a/src/libstrongswan/crypto/crypters/des_crypter.h +++ /dev/null @@ -1,58 +0,0 @@ -/** - * @file des_crypter.h - * - * @brief Interface of des_crypter_t - * - */ - -/* - * Copyright (C) 2006 Martin Willi - * Hochschule fuer Technik Rapperswil - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -#ifndef DES_CRYPTER_H_ -#define DES_CRYPTER_H_ - -typedef struct des_crypter_t des_crypter_t; - -#include <crypto/crypters/crypter.h> - - -/** - * @brief Class implementing the DES and 3DES encryption algorithms. - * - * @b Constructors: - * - des_crypter_create() - * - * @ingroup crypters - */ -struct des_crypter_t { - - /** - * The crypter_t interface. - */ - crypter_t crypter_interface; -}; - -/** - * @brief Constructor to create des_crypter_t objects. - * - * @param algo ENCR_DES for single DES, ENCR_3DES for triple DES - * @return - * - des_crypter_t object - * - NULL if algo not supported - */ -des_crypter_t *des_crypter_create(encryption_algorithm_t algo); - - -#endif /* DES_CRYPTER_H_ */ diff --git a/src/libstrongswan/crypto/crypto_factory.c b/src/libstrongswan/crypto/crypto_factory.c new file mode 100644 index 000000000..46fa983b2 --- /dev/null +++ b/src/libstrongswan/crypto/crypto_factory.c @@ -0,0 +1,571 @@ +/* + * Copyright (C) 2008 Martin Willi + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * $Id: crypto_factory.c 3806 2008-04-15 05:56:35Z martin $ + */ + +#include "crypto_factory.h" + +#include <utils/linked_list.h> +#include <utils/mutex.h> + +typedef struct crypter_entry_t crypter_entry_t; +struct crypter_entry_t { + /** encryption algorithm */ + encryption_algorithm_t algo; + /** associated constructor */ + crypter_constructor_t create; +}; + +typedef struct signer_entry_t signer_entry_t; +struct signer_entry_t { + /** integrity algorithm */ + integrity_algorithm_t algo; + /** associated constructor */ + signer_constructor_t create; +}; + +typedef struct hasher_entry_t hasher_entry_t; +struct hasher_entry_t { + /** hash algorithm */ + hash_algorithm_t algo; + /** associated constructor */ + hasher_constructor_t create; +}; + +typedef struct prf_entry_t prf_entry_t; +struct prf_entry_t { + /** hash algorithm */ + pseudo_random_function_t algo; + /** associated constructor */ + prf_constructor_t create; +}; + +typedef struct rng_entry_t rng_entry_t; +struct rng_entry_t { + /** quality of randomness */ + rng_quality_t quality; + /** associated constructor */ + rng_constructor_t create; +}; + +typedef struct dh_entry_t dh_entry_t; +struct dh_entry_t { + /** hash algorithm */ + diffie_hellman_group_t group; + /** associated constructor */ + dh_constructor_t create; +}; + +typedef struct private_crypto_factory_t private_crypto_factory_t; + +/** + * private data of crypto_factory + */ +struct private_crypto_factory_t { + + /** + * public functions + */ + crypto_factory_t public; + + /** + * registered crypters, as crypter_entry_t + */ + linked_list_t *crypters; + + /** + * registered signers, as signer_entry_t + */ + linked_list_t *signers; + + /** + * registered hashers, as hasher_entry_t + */ + linked_list_t *hashers; + + /** + * registered prfs, as prf_entry_t + */ + linked_list_t *prfs; + + /** + * registered rngs, as rng_entry_t + */ + linked_list_t *rngs; + + /** + * registered diffie hellman, as dh_entry_t + */ + linked_list_t *dhs; + + /** + * mutex to lock access to modules + */ + mutex_t *mutex; +}; + +/** + * Implementation of crypto_factory_t.create_crypter. + */ +static crypter_t* create_crypter(private_crypto_factory_t *this, + encryption_algorithm_t algo, size_t key_size) +{ + enumerator_t *enumerator; + crypter_entry_t *entry; + crypter_t *crypter = NULL; + + this->mutex->lock(this->mutex); + enumerator = this->crypters->create_enumerator(this->crypters); + while (enumerator->enumerate(enumerator, &entry)) + { + if (entry->algo == algo) + { + crypter = entry->create(algo, key_size); + if (crypter) + { + break; + } + } + } + enumerator->destroy(enumerator); + this->mutex->unlock(this->mutex); + return crypter; +} + +/** + * Implementation of crypto_factory_t.create_signer. + */ +static signer_t* create_signer(private_crypto_factory_t *this, + integrity_algorithm_t algo) +{ + enumerator_t *enumerator; + signer_entry_t *entry; + signer_t *signer = NULL; + + this->mutex->lock(this->mutex); + enumerator = this->signers->create_enumerator(this->signers); + while (enumerator->enumerate(enumerator, &entry)) + { + if (entry->algo == algo) + { + signer = entry->create(algo); + if (signer) + { + break; + } + } + } + enumerator->destroy(enumerator); + this->mutex->unlock(this->mutex); + + return signer; +} + +/** + * Implementation of crypto_factory_t.create_hasher. + */ +static hasher_t* create_hasher(private_crypto_factory_t *this, + hash_algorithm_t algo) +{ + enumerator_t *enumerator; + hasher_entry_t *entry; + hasher_t *hasher = NULL; + + this->mutex->lock(this->mutex); + enumerator = this->hashers->create_enumerator(this->hashers); + while (enumerator->enumerate(enumerator, &entry)) + { + if (algo == HASH_PREFERRED || entry->algo == algo) + { + hasher = entry->create(entry->algo); + if (hasher) + { + break; + } + } + } + enumerator->destroy(enumerator); + this->mutex->unlock(this->mutex); + return hasher; +} + +/** + * Implementation of crypto_factory_t.create_prf. + */ +static prf_t* create_prf(private_crypto_factory_t *this, + pseudo_random_function_t algo) +{ + enumerator_t *enumerator; + prf_entry_t *entry; + prf_t *prf = NULL; + + this->mutex->lock(this->mutex); + enumerator = this->prfs->create_enumerator(this->prfs); + while (enumerator->enumerate(enumerator, &entry)) + { + if (entry->algo == algo) + { + prf = entry->create(algo); + if (prf) + { + break; + } + } + } + enumerator->destroy(enumerator); + this->mutex->unlock(this->mutex); + return prf; +} + +/** + * Implementation of crypto_factory_t.create_rng. + */ +static rng_t* create_rng(private_crypto_factory_t *this, rng_quality_t quality) +{ + enumerator_t *enumerator; + rng_entry_t *entry; + u_int diff = ~0; + rng_constructor_t constr = NULL; + + this->mutex->lock(this->mutex); + enumerator = this->rngs->create_enumerator(this->rngs); + while (enumerator->enumerate(enumerator, &entry)) + { /* find the best matching quality, but at least as good as requested */ + if (entry->quality >= quality && diff > entry->quality - quality) + { + diff = entry->quality - quality; + constr = entry->create; + if (diff == 0) + { /* perfect match, won't get better */ + break; + } + } + } + enumerator->destroy(enumerator); + this->mutex->unlock(this->mutex); + if (constr) + { + return constr(quality); + } + return NULL; +} + +/** + * Implementation of crypto_factory_t.create_dh. + */ +static diffie_hellman_t* create_dh(private_crypto_factory_t *this, + diffie_hellman_group_t group) +{ + enumerator_t *enumerator; + dh_entry_t *entry; + diffie_hellman_t *diffie_hellman = NULL; + + this->mutex->lock(this->mutex); + enumerator = this->dhs->create_enumerator(this->dhs); + while (enumerator->enumerate(enumerator, &entry)) + { + if (entry->group == group) + { + diffie_hellman = entry->create(group); + if (diffie_hellman) + { + break; + } + } + } + enumerator->destroy(enumerator); + this->mutex->unlock(this->mutex); + return diffie_hellman; +} + +/** + * Implementation of crypto_factory_t.add_crypter. + */ +static void add_crypter(private_crypto_factory_t *this, + encryption_algorithm_t algo, + crypter_constructor_t create) +{ + crypter_entry_t *entry = malloc_thing(crypter_entry_t); + + entry->algo = algo; + entry->create = create; + this->mutex->lock(this->mutex); + this->crypters->insert_last(this->crypters, entry); + this->mutex->unlock(this->mutex); +} + +/** + * Implementation of crypto_factory_t.remove_crypter. + */ +static void remove_crypter(private_crypto_factory_t *this, + crypter_constructor_t create) +{ + crypter_entry_t *entry; + enumerator_t *enumerator; + + this->mutex->lock(this->mutex); + enumerator = this->crypters->create_enumerator(this->crypters); + while (enumerator->enumerate(enumerator, &entry)) + { + if (entry->create == create) + { + this->crypters->remove_at(this->crypters, enumerator); + free(entry); + } + } + enumerator->destroy(enumerator); + this->mutex->unlock(this->mutex); +} + +/** + * Implementation of crypto_factory_t.add_signer. + */ +static void add_signer(private_crypto_factory_t *this, + integrity_algorithm_t algo, signer_constructor_t create) +{ + signer_entry_t *entry = malloc_thing(signer_entry_t); + + entry->algo = algo; + entry->create = create; + this->mutex->lock(this->mutex); + this->signers->insert_last(this->signers, entry); + this->mutex->unlock(this->mutex); +} + +/** + * Implementation of crypto_factory_t.remove_signer. + */ +static void remove_signer(private_crypto_factory_t *this, + signer_constructor_t create) +{ + signer_entry_t *entry; + enumerator_t *enumerator; + + this->mutex->lock(this->mutex); + enumerator = this->signers->create_enumerator(this->signers); + while (enumerator->enumerate(enumerator, &entry)) + { + if (entry->create == create) + { + this->signers->remove_at(this->signers, enumerator); + free(entry); + } + } + enumerator->destroy(enumerator); + this->mutex->unlock(this->mutex); +} + +/** + * Implementation of crypto_factory_t.add_hasher. + */ +static void add_hasher(private_crypto_factory_t *this, hash_algorithm_t algo, + hasher_constructor_t create) +{ + hasher_entry_t *entry = malloc_thing(hasher_entry_t); + + entry->algo = algo; + entry->create = create; + this->mutex->lock(this->mutex); + this->hashers->insert_last(this->hashers, entry); + this->mutex->unlock(this->mutex); +} + +/** + * Implementation of crypto_factory_t.remove_hasher. + */ +static void remove_hasher(private_crypto_factory_t *this, + hasher_constructor_t create) +{ + hasher_entry_t *entry; + enumerator_t *enumerator; + + this->mutex->lock(this->mutex); + enumerator = this->hashers->create_enumerator(this->hashers); + while (enumerator->enumerate(enumerator, &entry)) + { + if (entry->create == create) + { + this->hashers->remove_at(this->hashers, enumerator); + free(entry); + } + } + enumerator->destroy(enumerator); + this->mutex->unlock(this->mutex); +} + +/** + * Implementation of crypto_factory_t.add_prf. + */ +static void add_prf(private_crypto_factory_t *this, + pseudo_random_function_t algo, prf_constructor_t create) +{ + prf_entry_t *entry = malloc_thing(prf_entry_t); + + entry->algo = algo; + entry->create = create; + this->mutex->lock(this->mutex); + this->prfs->insert_last(this->prfs, entry); + this->mutex->unlock(this->mutex); +} + +/** + * Implementation of crypto_factory_t.remove_prf. + */ +static void remove_prf(private_crypto_factory_t *this, prf_constructor_t create) +{ + prf_entry_t *entry; + enumerator_t *enumerator; + + this->mutex->lock(this->mutex); + enumerator = this->prfs->create_enumerator(this->prfs); + while (enumerator->enumerate(enumerator, &entry)) + { + if (entry->create == create) + { + this->prfs->remove_at(this->prfs, enumerator); + free(entry); + } + } + enumerator->destroy(enumerator); + this->mutex->unlock(this->mutex); +} + +/** + * Implementation of crypto_factory_t.add_rng. + */ +static void add_rng(private_crypto_factory_t *this, rng_quality_t quality, + rng_constructor_t create) +{ + rng_entry_t *entry = malloc_thing(rng_entry_t); + + entry->quality = quality; + entry->create = create; + this->mutex->lock(this->mutex); + this->rngs->insert_last(this->rngs, entry); + this->mutex->unlock(this->mutex); +} + +/** + * Implementation of crypto_factory_t.remove_rng. + */ +static void remove_rng(private_crypto_factory_t *this, rng_constructor_t create) +{ + rng_entry_t *entry; + enumerator_t *enumerator; + + this->mutex->lock(this->mutex); + enumerator = this->rngs->create_enumerator(this->rngs); + while (enumerator->enumerate(enumerator, &entry)) + { + if (entry->create == create) + { + this->rngs->remove_at(this->rngs, enumerator); + free(entry); + } + } + enumerator->destroy(enumerator); + this->mutex->unlock(this->mutex); +} + +/** + * Implementation of crypto_factory_t.add_dh. + */ +static void add_dh(private_crypto_factory_t *this, diffie_hellman_group_t group, + dh_constructor_t create) +{ + dh_entry_t *entry = malloc_thing(dh_entry_t); + + entry->group = group; + entry->create = create; + this->mutex->lock(this->mutex); + this->dhs->insert_last(this->dhs, entry); + this->mutex->unlock(this->mutex); +} + +/** + * Implementation of crypto_factory_t.remove_dh. + */ +static void remove_dh(private_crypto_factory_t *this, dh_constructor_t create) +{ + dh_entry_t *entry; + enumerator_t *enumerator; + + this->mutex->lock(this->mutex); + enumerator = this->dhs->create_enumerator(this->dhs); + while (enumerator->enumerate(enumerator, &entry)) + { + if (entry->create == create) + { + this->dhs->remove_at(this->dhs, enumerator); + free(entry); + } + } + enumerator->destroy(enumerator); + this->mutex->unlock(this->mutex); +} + +/** + * Implementation of crypto_factory_t.destroy + */ +static void destroy(private_crypto_factory_t *this) +{ + this->crypters->destroy_function(this->crypters, free); + this->signers->destroy_function(this->signers, free); + this->hashers->destroy_function(this->hashers, free); + this->prfs->destroy_function(this->prfs, free); + this->rngs->destroy_function(this->rngs, free); + this->dhs->destroy_function(this->dhs, free); + this->mutex->destroy(this->mutex); + free(this); +} + +/* + * see header file + */ +crypto_factory_t *crypto_factory_create() +{ + private_crypto_factory_t *this = malloc_thing(private_crypto_factory_t); + + this->public.create_crypter = (crypter_t*(*)(crypto_factory_t*, encryption_algorithm_t, size_t))create_crypter; + this->public.create_signer = (signer_t*(*)(crypto_factory_t*, integrity_algorithm_t))create_signer; + this->public.create_hasher = (hasher_t*(*)(crypto_factory_t*, hash_algorithm_t))create_hasher; + this->public.create_prf = (prf_t*(*)(crypto_factory_t*, pseudo_random_function_t))create_prf; + this->public.create_rng = (rng_t*(*)(crypto_factory_t*, rng_quality_t quality))create_rng; + this->public.create_dh = (diffie_hellman_t*(*)(crypto_factory_t*, diffie_hellman_group_t group))create_dh; + this->public.add_crypter = (void(*)(crypto_factory_t*, encryption_algorithm_t algo, crypter_constructor_t create))add_crypter; + this->public.remove_crypter = (void(*)(crypto_factory_t*, crypter_constructor_t create))remove_crypter; + this->public.add_signer = (void(*)(crypto_factory_t*, integrity_algorithm_t algo, signer_constructor_t create))add_signer; + this->public.remove_signer = (void(*)(crypto_factory_t*, signer_constructor_t create))remove_signer; + this->public.add_hasher = (void(*)(crypto_factory_t*, hash_algorithm_t algo, hasher_constructor_t create))add_hasher; + this->public.remove_hasher = (void(*)(crypto_factory_t*, hasher_constructor_t create))remove_hasher; + this->public.add_prf = (void(*)(crypto_factory_t*, pseudo_random_function_t algo, prf_constructor_t create))add_prf; + this->public.remove_prf = (void(*)(crypto_factory_t*, prf_constructor_t create))remove_prf; + this->public.add_rng = (void(*)(crypto_factory_t*, rng_quality_t quality, rng_constructor_t create))add_rng; + this->public.remove_rng = (void(*)(crypto_factory_t*, rng_constructor_t create))remove_rng; + this->public.add_dh = (void(*)(crypto_factory_t*, diffie_hellman_group_t algo, dh_constructor_t create))add_dh; + this->public.remove_dh = (void(*)(crypto_factory_t*, dh_constructor_t create))remove_dh; + this->public.destroy = (void(*)(crypto_factory_t*))destroy; + + this->crypters = linked_list_create(); + this->signers = linked_list_create(); + this->hashers = linked_list_create(); + this->prfs = linked_list_create(); + this->rngs = linked_list_create(); + this->dhs = linked_list_create(); + this->mutex = mutex_create(MUTEX_RECURSIVE); + + return &this->public; +} + diff --git a/src/libstrongswan/crypto/crypto_factory.h b/src/libstrongswan/crypto/crypto_factory.h new file mode 100644 index 000000000..6bf070c31 --- /dev/null +++ b/src/libstrongswan/crypto/crypto_factory.h @@ -0,0 +1,235 @@ +/* + * Copyright (C) 2008 Martin Willi + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +/** + * @defgroup crypto_factory crypto_factory + * @{ @ingroup crypto + */ + +#ifndef CRYPTO_FACTORY_H_ +#define CRYPTO_FACTORY_H_ + +typedef struct crypto_factory_t crypto_factory_t; + +#include <library.h> +#include <crypto/crypters/crypter.h> +#include <crypto/signers/signer.h> +#include <crypto/hashers/hasher.h> +#include <crypto/prfs/prf.h> +#include <crypto/rngs/rng.h> +#include <crypto/diffie_hellman.h> + +/** + * Constructor function for crypters + */ +typedef crypter_t* (*crypter_constructor_t)(encryption_algorithm_t algo, + size_t key_size); +/** + * Constructor function for signers + */ +typedef signer_t* (*signer_constructor_t)(integrity_algorithm_t algo); + +/** + * Constructor function for hashers + */ +typedef hasher_t* (*hasher_constructor_t)(hash_algorithm_t algo); + +/** + * Constructor function for pseudo random functions + */ +typedef prf_t* (*prf_constructor_t)(pseudo_random_function_t algo); + +/** + * Constructor function for source of randomness + */ +typedef rng_t* (*rng_constructor_t)(rng_quality_t quality); + +/** + * Constructor function for diffie hellman + */ +typedef diffie_hellman_t* (*dh_constructor_t)(diffie_hellman_group_t group); + +/** + * Handles crypto modules and creates instances. + */ +struct crypto_factory_t { + + /** + * Create a crypter instance. + * + * @param algo encryption algorithm + * @param key_size length of the key in bytes + * @return crypter_t instance, NULL if not supported + */ + crypter_t* (*create_crypter)(crypto_factory_t *this, + encryption_algorithm_t algo, size_t key_size); + + /** + * Create a symmetric signer instance. + * + * @param algo MAC algorithm to use + * @return signer_t instance, NULL if not supported + */ + signer_t* (*create_signer)(crypto_factory_t *this, + integrity_algorithm_t algo); + + /** + * Create a hasher instance. + * + * @param algo hash algorithm + * @return hasher_t instance, NULL if not supported + */ + hasher_t* (*create_hasher)(crypto_factory_t *this, hash_algorithm_t algo); + + /** + * Create a pseudo random function instance. + * + * @param algo PRF algorithm to use + * @return prf_t instance, NULL if not supported + */ + prf_t* (*create_prf)(crypto_factory_t *this, pseudo_random_function_t algo); + + /** + * Create a source of randomness. + * + * @param quality required randomness quality + * @return rng_t instance, NULL if no RNG with such a quality + */ + rng_t* (*create_rng)(crypto_factory_t *this, rng_quality_t quality); + + /** + * Create a diffie hellman instance. + * + * @param group diffie hellman group + * @return diffie_hellman_t instance, NULL if not supported + */ + diffie_hellman_t* (*create_dh)(crypto_factory_t *this, + diffie_hellman_group_t group); + + /** + * Register a crypter constructor. + * + * @param algo algorithm to constructor + * @param create constructor function for that algorithm + * @return + */ + void (*add_crypter)(crypto_factory_t *this, encryption_algorithm_t algo, + crypter_constructor_t create); + + /** + * Unregister a crypter constructor. + * + * @param create constructor function to unregister + */ + void (*remove_crypter)(crypto_factory_t *this, crypter_constructor_t create); + + /** + * Register a signer constructor. + * + * @param algo algorithm to constructor + * @param create constructor function for that algorithm + * @return + */ + void (*add_signer)(crypto_factory_t *this, integrity_algorithm_t algo, + signer_constructor_t create); + + /** + * Unregister a signer constructor. + * + * @param create constructor function to unregister + */ + void (*remove_signer)(crypto_factory_t *this, signer_constructor_t create); + + /** + * Register a hasher constructor. + * + * The first added hasher is the preferred hasher returned on + * create_hasher(HASH_PREFERRED). + * + * @param algo algorithm to constructor + * @param create constructor function for that algorithm + * @return + */ + void (*add_hasher)(crypto_factory_t *this, hash_algorithm_t algo, + hasher_constructor_t create); + + /** + * Unregister a hasher constructor. + * + * @param create constructor function to unregister + */ + void (*remove_hasher)(crypto_factory_t *this, hasher_constructor_t create); + + /** + * Register a prf constructor. + * + * @param algo algorithm to constructor + * @param create constructor function for that algorithm + * @return + */ + void (*add_prf)(crypto_factory_t *this, pseudo_random_function_t algo, + prf_constructor_t create); + + /** + * Unregister a prf constructor. + * + * @param create constructor function to unregister + */ + void (*remove_prf)(crypto_factory_t *this, prf_constructor_t create); + + /** + * Register a source of randomness. + * + * @param quality quality of randomness this RNG serves + * @param create constructor function for such a quality + */ + void (*add_rng)(crypto_factory_t *this, rng_quality_t quality, rng_constructor_t create); + + /** + * Unregister a source of randomness. + * + * @param create constructor function to unregister + */ + void (*remove_rng)(crypto_factory_t *this, rng_constructor_t create); + + /** + * Register a diffie hellman constructor. + * + * @param group dh group to constructor + * @param create constructor function for that algorithm + * @return + */ + void (*add_dh)(crypto_factory_t *this, diffie_hellman_group_t group, + dh_constructor_t create); + + /** + * Unregister a diffie hellman constructor. + * + * @param create constructor function to unregister + */ + void (*remove_dh)(crypto_factory_t *this, dh_constructor_t create); + + /** + * Destroy a crypto_factory instance. + */ + void (*destroy)(crypto_factory_t *this); +}; + +/** + * Create a crypto_factory instance. + */ +crypto_factory_t *crypto_factory_create(); + +#endif /* CRYPTO_FACTORY_H_ @}*/ diff --git a/src/libstrongswan/crypto/diffie_hellman.c b/src/libstrongswan/crypto/diffie_hellman.c index 605892e87..02d2cb52a 100644 --- a/src/libstrongswan/crypto/diffie_hellman.c +++ b/src/libstrongswan/crypto/diffie_hellman.c @@ -1,14 +1,5 @@ -/** - * @file diffie_hellman.c - * - * @brief Implementation of diffie_hellman_t. - * - */ - /* - * Copyright (C) 1998-2002 D. Hugh Redelmeier. - * Copyright (C) 1999, 2000, 2001 Henry Spencer. - * Copyright (C) 2005-2007 Martin Willi + * Copyright (C) 2005-2008 Martin Willi * Copyright (C) 2005 Jan Hutter * Hochschule fuer Technik Rapperswil * @@ -21,569 +12,29 @@ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. + * + * $Id: diffie_hellman.c 4023 2008-05-29 06:55:03Z andreas $ */ -#include <gmp.h> - #include "diffie_hellman.h" -#include <utils/randomizer.h> -#include <debug.h> - ENUM_BEGIN(diffie_hellman_group_names, MODP_NONE, MODP_1024_BIT, "MODP_NONE", "MODP_768_BIT", "MODP_1024_BIT"); ENUM_NEXT(diffie_hellman_group_names, MODP_1536_BIT, MODP_1536_BIT, MODP_1024_BIT, "MODP_1536_BIT"); -ENUM_NEXT(diffie_hellman_group_names, MODP_2048_BIT, MODP_8192_BIT, MODP_1536_BIT, +ENUM_NEXT(diffie_hellman_group_names, MODP_2048_BIT, ECP_521_BIT, MODP_1536_BIT, "MODP_2048_BIT", "MODP_3072_BIT", "MODP_4096_BIT", "MODP_6144_BIT", - "MODP_8192_BIT"); -ENUM_END(diffie_hellman_group_names, MODP_8192_BIT); - - -/** - * Modulus of Group 1 (MODP_768_BIT). - */ -static u_int8_t group1_modulus[] = { - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC9,0x0F,0xDA,0xA2,0x21,0x68,0xC2,0x34, - 0xC4,0xC6,0x62,0x8B,0x80 ,0xDC,0x1C,0xD1,0x29,0x02,0x4E,0x08,0x8A,0x67,0xCC,0x74, - 0x02,0x0B,0xBE,0xA6,0x3B,0x13,0x9B,0x22,0x51,0x4A,0x08,0x79,0x8E,0x34,0x04,0xDD, - 0xEF,0x95,0x19,0xB3,0xCD,0x3A,0x43,0x1B,0x30,0x2B,0x0A,0x6D,0xF2,0x5F,0x14,0x37, - 0x4F,0xE1,0x35,0x6D,0x6D,0x51,0xC2,0x45,0xE4,0x85,0xB5,0x76,0x62,0x5E,0x7E,0xC6, - 0xF4,0x4C,0x42,0xE9,0xA6,0x3A,0x36,0x20,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF -}; - -/** - * Modulus of Group 2 (MODP_1024_BIT). - */ -static u_int8_t group2_modulus[] = { - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC9,0x0F,0xDA,0xA2,0x21,0x68,0xC2,0x34, - 0xC4,0xC6,0x62,0x8B,0x80,0xDC,0x1C,0xD1,0x29,0x02,0x4E,0x08,0x8A,0x67,0xCC,0x74, - 0x02,0x0B,0xBE,0xA6,0x3B,0x13,0x9B,0x22,0x51,0x4A,0x08,0x79,0x8E,0x34,0x04,0xDD, - 0xEF,0x95,0x19,0xB3,0xCD,0x3A,0x43,0x1B,0x30,0x2B,0x0A,0x6D,0xF2,0x5F,0x14,0x37, - 0x4F,0xE1,0x35,0x6D,0x6D,0x51,0xC2,0x45,0xE4,0x85,0xB5,0x76,0x62,0x5E,0x7E,0xC6, - 0xF4,0x4C,0x42,0xE9,0xA6,0x37,0xED,0x6B,0x0B,0xFF,0x5C,0xB6,0xF4,0x06,0xB7,0xED, - 0xEE,0x38,0x6B,0xFB,0x5A,0x89,0x9F,0xA5,0xAE,0x9F,0x24,0x11,0x7C,0x4B,0x1F,0xE6, - 0x49,0x28,0x66,0x51,0xEC,0xE6,0x53,0x81,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF -}; - -/** - * Modulus of Group 5 (MODP_1536_BIT). - */ -static u_int8_t group5_modulus[] = { - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC9,0x0F,0xDA,0xA2,0x21,0x68,0xC2,0x34, - 0xC4,0xC6,0x62,0x8B,0x80,0xDC,0x1C,0xD1,0x29,0x02,0x4E,0x08,0x8A,0x67,0xCC,0x74, - 0x02,0x0B,0xBE,0xA6,0x3B,0x13,0x9B,0x22,0x51,0x4A,0x08,0x79,0x8E,0x34,0x04,0xDD, - 0xEF,0x95,0x19,0xB3,0xCD,0x3A,0x43,0x1B,0x30,0x2B,0x0A,0x6D,0xF2,0x5F,0x14,0x37, - 0x4F,0xE1,0x35,0x6D,0x6D,0x51,0xC2,0x45,0xE4,0x85,0xB5,0x76,0x62,0x5E,0x7E,0xC6, - 0xF4,0x4C,0x42,0xE9,0xA6,0x37,0xED,0x6B,0x0B,0xFF,0x5C,0xB6,0xF4,0x06,0xB7,0xED, - 0xEE,0x38,0x6B,0xFB,0x5A,0x89,0x9F,0xA5,0xAE,0x9F,0x24,0x11,0x7C,0x4B,0x1F,0xE6, - 0x49,0x28,0x66,0x51,0xEC,0xE4,0x5B,0x3D,0xC2,0x00,0x7C,0xB8,0xA1,0x63,0xBF,0x05, - 0x98,0xDA,0x48,0x36,0x1C,0x55,0xD3,0x9A,0x69,0x16,0x3F,0xA8,0xFD,0x24,0xCF,0x5F, - 0x83,0x65,0x5D,0x23,0xDC,0xA3,0xAD,0x96,0x1C,0x62,0xF3,0x56,0x20,0x85,0x52,0xBB, - 0x9E,0xD5,0x29,0x07,0x70,0x96,0x96,0x6D,0x67,0x0C,0x35,0x4E,0x4A,0xBC,0x98,0x04, - 0xF1,0x74,0x6C,0x08,0xCA,0x23,0x73,0x27,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF -}; -/** - * Modulus of Group 14 (MODP_2048_BIT). - */ -static u_int8_t group14_modulus[] = { - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC9,0x0F,0xDA,0xA2,0x21,0x68,0xC2,0x34, - 0xC4,0xC6,0x62,0x8B,0x80,0xDC,0x1C,0xD1,0x29,0x02,0x4E,0x08,0x8A,0x67,0xCC,0x74, - 0x02,0x0B,0xBE,0xA6,0x3B,0x13,0x9B,0x22,0x51,0x4A,0x08,0x79,0x8E,0x34,0x04,0xDD, - 0xEF,0x95,0x19,0xB3,0xCD,0x3A,0x43,0x1B,0x30,0x2B,0x0A,0x6D,0xF2,0x5F,0x14,0x37, - 0x4F,0xE1,0x35,0x6D,0x6D,0x51,0xC2,0x45,0xE4,0x85,0xB5,0x76,0x62,0x5E,0x7E,0xC6, - 0xF4,0x4C,0x42,0xE9,0xA6,0x37,0xED,0x6B,0x0B,0xFF,0x5C,0xB6,0xF4,0x06,0xB7,0xED, - 0xEE,0x38,0x6B,0xFB,0x5A,0x89,0x9F,0xA5,0xAE,0x9F,0x24,0x11,0x7C,0x4B,0x1F,0xE6, - 0x49,0x28,0x66,0x51,0xEC,0xE4,0x5B,0x3D,0xC2,0x00,0x7C,0xB8,0xA1,0x63,0xBF,0x05, - 0x98,0xDA,0x48,0x36,0x1C,0x55,0xD3,0x9A,0x69,0x16,0x3F,0xA8,0xFD,0x24,0xCF,0x5F, - 0x83,0x65,0x5D,0x23,0xDC,0xA3,0xAD,0x96,0x1C,0x62,0xF3,0x56,0x20,0x85,0x52,0xBB, - 0x9E,0xD5,0x29,0x07,0x70,0x96,0x96,0x6D,0x67,0x0C,0x35,0x4E,0x4A,0xBC,0x98,0x04, - 0xF1,0x74,0x6C,0x08,0xCA,0x18,0x21,0x7C,0x32,0x90,0x5E,0x46,0x2E,0x36,0xCE,0x3B, - 0xE3,0x9E,0x77,0x2C,0x18,0x0E,0x86,0x03,0x9B,0x27,0x83,0xA2,0xEC,0x07,0xA2,0x8F, - 0xB5,0xC5,0x5D,0xF0,0x6F,0x4C,0x52,0xC9,0xDE,0x2B,0xCB,0xF6,0x95,0x58,0x17,0x18, - 0x39,0x95,0x49,0x7C,0xEA,0x95,0x6A,0xE5,0x15,0xD2,0x26,0x18,0x98,0xFA,0x05,0x10, - 0x15,0x72,0x8E,0x5A,0x8A,0xAC,0xAA,0x68,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF -}; - -/** - * Modulus of Group 15 (MODP_3072_BIT). - */ -static u_int8_t group15_modulus[] = { - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC9,0x0F,0xDA,0xA2,0x21,0x68,0xC2,0x34, - 0xC4,0xC6,0x62,0x8B,0x80,0xDC,0x1C,0xD1,0x29,0x02,0x4E,0x08,0x8A,0x67,0xCC,0x74, - 0x02,0x0B,0xBE,0xA6,0x3B,0x13,0x9B,0x22,0x51,0x4A,0x08,0x79,0x8E,0x34,0x04,0xDD, - 0xEF,0x95,0x19,0xB3,0xCD,0x3A,0x43,0x1B,0x30,0x2B,0x0A,0x6D,0xF2,0x5F,0x14,0x37, - 0x4F,0xE1,0x35,0x6D,0x6D,0x51,0xC2,0x45,0xE4,0x85,0xB5,0x76,0x62,0x5E,0x7E,0xC6, - 0xF4,0x4C,0x42,0xE9,0xA6,0x37,0xED,0x6B,0x0B,0xFF,0x5C,0xB6,0xF4,0x06,0xB7,0xED, - 0xEE,0x38,0x6B,0xFB,0x5A,0x89,0x9F,0xA5,0xAE,0x9F,0x24,0x11,0x7C,0x4B,0x1F,0xE6, - 0x49,0x28,0x66,0x51,0xEC,0xE4,0x5B,0x3D,0xC2,0x00,0x7C,0xB8,0xA1,0x63,0xBF,0x05, - 0x98,0xDA,0x48,0x36,0x1C,0x55,0xD3,0x9A,0x69,0x16,0x3F,0xA8,0xFD,0x24,0xCF,0x5F, - 0x83,0x65,0x5D,0x23,0xDC,0xA3,0xAD,0x96,0x1C,0x62,0xF3,0x56,0x20,0x85,0x52,0xBB, - 0x9E,0xD5,0x29,0x07,0x70,0x96,0x96,0x6D,0x67,0x0C,0x35,0x4E,0x4A,0xBC,0x98,0x04, - 0xF1,0x74,0x6C,0x08,0xCA,0x18,0x21,0x7C,0x32,0x90,0x5E,0x46,0x2E,0x36,0xCE,0x3B, - 0xE3,0x9E,0x77,0x2C,0x18,0x0E,0x86,0x03,0x9B,0x27,0x83,0xA2,0xEC,0x07,0xA2,0x8F, - 0xB5,0xC5,0x5D,0xF0,0x6F,0x4C,0x52,0xC9,0xDE,0x2B,0xCB,0xF6,0x95,0x58,0x17,0x18, - 0x39,0x95,0x49,0x7C,0xEA,0x95,0x6A,0xE5,0x15,0xD2,0x26,0x18,0x98,0xFA,0x05,0x10, - 0x15,0x72,0x8E,0x5A,0x8A,0xAA,0xC4,0x2D,0xAD,0x33,0x17,0x0D,0x04,0x50,0x7A,0x33, - 0xA8,0x55,0x21,0xAB,0xDF,0x1C,0xBA,0x64,0xEC,0xFB,0x85,0x04,0x58,0xDB,0xEF,0x0A, - 0x8A,0xEA,0x71,0x57,0x5D,0x06,0x0C,0x7D,0xB3,0x97,0x0F,0x85,0xA6,0xE1,0xE4,0xC7, - 0xAB,0xF5,0xAE,0x8C,0xDB,0x09,0x33,0xD7,0x1E,0x8C,0x94,0xE0,0x4A,0x25,0x61,0x9D, - 0xCE,0xE3,0xD2,0x26,0x1A,0xD2,0xEE,0x6B,0xF1,0x2F,0xFA,0x06,0xD9,0x8A,0x08,0x64, - 0xD8,0x76,0x02,0x73,0x3E,0xC8,0x6A,0x64,0x52,0x1F,0x2B,0x18,0x17,0x7B,0x20,0x0C, - 0xBB,0xE1,0x17,0x57,0x7A,0x61,0x5D,0x6C,0x77,0x09,0x88,0xC0,0xBA,0xD9,0x46,0xE2, - 0x08,0xE2,0x4F,0xA0,0x74,0xE5,0xAB,0x31,0x43,0xDB,0x5B,0xFC,0xE0,0xFD,0x10,0x8E, - 0x4B,0x82,0xD1,0x20,0xA9,0x3A,0xD2,0xCA,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF -}; - -/** - * Modulus of Group 16 (MODP_4096_BIT). - */ -static u_int8_t group16_modulus[] = { - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC9,0x0F,0xDA,0xA2,0x21,0x68,0xC2,0x34, - 0xC4,0xC6,0x62,0x8B,0x80,0xDC,0x1C,0xD1,0x29,0x02,0x4E,0x08,0x8A,0x67,0xCC,0x74, - 0x02,0x0B,0xBE,0xA6,0x3B,0x13,0x9B,0x22,0x51,0x4A,0x08,0x79,0x8E,0x34,0x04,0xDD, - 0xEF,0x95,0x19,0xB3,0xCD,0x3A,0x43,0x1B,0x30,0x2B,0x0A,0x6D,0xF2,0x5F,0x14,0x37, - 0x4F,0xE1,0x35,0x6D,0x6D,0x51,0xC2,0x45,0xE4,0x85,0xB5,0x76,0x62,0x5E,0x7E,0xC6, - 0xF4,0x4C,0x42,0xE9,0xA6,0x37,0xED,0x6B,0x0B,0xFF,0x5C,0xB6,0xF4,0x06,0xB7,0xED, - 0xEE,0x38,0x6B,0xFB,0x5A,0x89,0x9F,0xA5,0xAE,0x9F,0x24,0x11,0x7C,0x4B,0x1F,0xE6, - 0x49,0x28,0x66,0x51,0xEC,0xE4,0x5B,0x3D,0xC2,0x00,0x7C,0xB8,0xA1,0x63,0xBF,0x05, - 0x98,0xDA,0x48,0x36,0x1C,0x55,0xD3,0x9A,0x69,0x16,0x3F,0xA8,0xFD,0x24,0xCF,0x5F, - 0x83,0x65,0x5D,0x23,0xDC,0xA3,0xAD,0x96,0x1C,0x62,0xF3,0x56,0x20,0x85,0x52,0xBB, - 0x9E,0xD5,0x29,0x07,0x70,0x96,0x96,0x6D,0x67,0x0C,0x35,0x4E,0x4A,0xBC,0x98,0x04, - 0xF1,0x74,0x6C,0x08,0xCA,0x18,0x21,0x7C,0x32,0x90,0x5E,0x46,0x2E,0x36,0xCE,0x3B, - 0xE3,0x9E,0x77,0x2C,0x18,0x0E,0x86,0x03,0x9B,0x27,0x83,0xA2,0xEC,0x07,0xA2,0x8F, - 0xB5,0xC5,0x5D,0xF0,0x6F,0x4C,0x52,0xC9,0xDE,0x2B,0xCB,0xF6,0x95,0x58,0x17,0x18, - 0x39,0x95,0x49,0x7C,0xEA,0x95,0x6A,0xE5,0x15,0xD2,0x26,0x18,0x98,0xFA,0x05,0x10, - 0x15,0x72,0x8E,0x5A,0x8A,0xAA,0xC4,0x2D,0xAD,0x33,0x17,0x0D,0x04,0x50,0x7A,0x33, - 0xA8,0x55,0x21,0xAB,0xDF,0x1C,0xBA,0x64,0xEC,0xFB,0x85,0x04,0x58,0xDB,0xEF,0x0A, - 0x8A,0xEA,0x71,0x57,0x5D,0x06,0x0C,0x7D,0xB3,0x97,0x0F,0x85,0xA6,0xE1,0xE4,0xC7, - 0xAB,0xF5,0xAE,0x8C,0xDB,0x09,0x33,0xD7,0x1E,0x8C,0x94,0xE0,0x4A,0x25,0x61,0x9D, - 0xCE,0xE3,0xD2,0x26,0x1A,0xD2,0xEE,0x6B,0xF1,0x2F,0xFA,0x06,0xD9,0x8A,0x08,0x64, - 0xD8,0x76,0x02,0x73,0x3E,0xC8,0x6A,0x64,0x52,0x1F,0x2B,0x18,0x17,0x7B,0x20,0x0C, - 0xBB,0xE1,0x17,0x57,0x7A,0x61,0x5D,0x6C,0x77,0x09,0x88,0xC0,0xBA,0xD9,0x46,0xE2, - 0x08,0xE2,0x4F,0xA0,0x74,0xE5,0xAB,0x31,0x43,0xDB,0x5B,0xFC,0xE0,0xFD,0x10,0x8E, - 0x4B,0x82,0xD1,0x20,0xA9,0x21,0x08,0x01,0x1A,0x72,0x3C,0x12,0xA7,0x87,0xE6,0xD7, - 0x88,0x71,0x9A,0x10,0xBD,0xBA,0x5B,0x26,0x99,0xC3,0x27,0x18,0x6A,0xF4,0xE2,0x3C, - 0x1A,0x94,0x68,0x34,0xB6,0x15,0x0B,0xDA,0x25,0x83,0xE9,0xCA,0x2A,0xD4,0x4C,0xE8, - 0xDB,0xBB,0xC2,0xDB,0x04,0xDE,0x8E,0xF9,0x2E,0x8E,0xFC,0x14,0x1F,0xBE,0xCA,0xA6, - 0x28,0x7C,0x59,0x47,0x4E,0x6B,0xC0,0x5D,0x99,0xB2,0x96,0x4F,0xA0,0x90,0xC3,0xA2, - 0x23,0x3B,0xA1,0x86,0x51,0x5B,0xE7,0xED,0x1F,0x61,0x29,0x70,0xCE,0xE2,0xD7,0xAF, - 0xB8,0x1B,0xDD,0x76,0x21,0x70,0x48,0x1C,0xD0,0x06,0x91,0x27,0xD5,0xB0,0x5A,0xA9, - 0x93,0xB4,0xEA,0x98,0x8D,0x8F,0xDD,0xC1,0x86,0xFF,0xB7,0xDC,0x90,0xA6,0xC0,0x8F, - 0x4D,0xF4,0x35,0xC9,0x34,0x06,0x31,0x99,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF -}; - -/** - * Modulus of Group 17 (MODP_6144_BIT). - */ -static u_int8_t group17_modulus[] = { - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC9,0x0F,0xDA,0xA2,0x21,0x68,0xC2,0x34, - 0xC4,0xC6,0x62,0x8B,0x80,0xDC,0x1C,0xD1,0x29,0x02,0x4E,0x08,0x8A,0x67,0xCC,0x74, - 0x02,0x0B,0xBE,0xA6,0x3B,0x13,0x9B,0x22,0x51,0x4A,0x08,0x79,0x8E,0x34,0x04,0xDD, - 0xEF,0x95,0x19,0xB3,0xCD,0x3A,0x43,0x1B,0x30,0x2B,0x0A,0x6D,0xF2,0x5F,0x14,0x37, - 0x4F,0xE1,0x35,0x6D,0x6D,0x51,0xC2,0x45,0xE4,0x85,0xB5,0x76,0x62,0x5E,0x7E,0xC6, - 0xF4,0x4C,0x42,0xE9,0xA6,0x37,0xED,0x6B,0x0B,0xFF,0x5C,0xB6,0xF4,0x06,0xB7,0xED, - 0xEE,0x38,0x6B,0xFB,0x5A,0x89,0x9F,0xA5,0xAE,0x9F,0x24,0x11,0x7C,0x4B,0x1F,0xE6, - 0x49,0x28,0x66,0x51,0xEC,0xE4,0x5B,0x3D,0xC2,0x00,0x7C,0xB8,0xA1,0x63,0xBF,0x05, - 0x98,0xDA,0x48,0x36,0x1C,0x55,0xD3,0x9A,0x69,0x16,0x3F,0xA8,0xFD,0x24,0xCF,0x5F, - 0x83,0x65,0x5D,0x23,0xDC,0xA3,0xAD,0x96,0x1C,0x62,0xF3,0x56,0x20,0x85,0x52,0xBB, - 0x9E,0xD5,0x29,0x07,0x70,0x96,0x96,0x6D,0x67,0x0C,0x35,0x4E,0x4A,0xBC,0x98,0x04, - 0xF1,0x74,0x6C,0x08,0xCA,0x18,0x21,0x7C,0x32,0x90,0x5E,0x46,0x2E,0x36,0xCE,0x3B, - 0xE3,0x9E,0x77,0x2C,0x18,0x0E,0x86,0x03,0x9B,0x27,0x83,0xA2,0xEC,0x07,0xA2,0x8F, - 0xB5,0xC5,0x5D,0xF0,0x6F,0x4C,0x52,0xC9,0xDE,0x2B,0xCB,0xF6,0x95,0x58,0x17,0x18, - 0x39,0x95,0x49,0x7C,0xEA,0x95,0x6A,0xE5,0x15,0xD2,0x26,0x18,0x98,0xFA,0x05,0x10, - 0x15,0x72,0x8E,0x5A,0x8A,0xAA,0xC4,0x2D,0xAD,0x33,0x17,0x0D,0x04,0x50,0x7A,0x33, - 0xA8,0x55,0x21,0xAB,0xDF,0x1C,0xBA,0x64,0xEC,0xFB,0x85,0x04,0x58,0xDB,0xEF,0x0A, - 0x8A,0xEA,0x71,0x57,0x5D,0x06,0x0C,0x7D,0xB3,0x97,0x0F,0x85,0xA6,0xE1,0xE4,0xC7, - 0xAB,0xF5,0xAE,0x8C,0xDB,0x09,0x33,0xD7,0x1E,0x8C,0x94,0xE0,0x4A,0x25,0x61,0x9D, - 0xCE,0xE3,0xD2,0x26,0x1A,0xD2,0xEE,0x6B,0xF1,0x2F,0xFA,0x06,0xD9,0x8A,0x08,0x64, - 0xD8,0x76,0x02,0x73,0x3E,0xC8,0x6A,0x64,0x52,0x1F,0x2B,0x18,0x17,0x7B,0x20,0x0C, - 0xBB,0xE1,0x17,0x57,0x7A,0x61,0x5D,0x6C,0x77,0x09,0x88,0xC0,0xBA,0xD9,0x46,0xE2, - 0x08,0xE2,0x4F,0xA0,0x74,0xE5,0xAB,0x31,0x43,0xDB,0x5B,0xFC,0xE0,0xFD,0x10,0x8E, - 0x4B,0x82,0xD1,0x20,0xA9,0x21,0x08,0x01,0x1A,0x72,0x3C,0x12,0xA7,0x87,0xE6,0xD7, - 0x88,0x71,0x9A,0x10,0xBD,0xBA,0x5B,0x26,0x99,0xC3,0x27,0x18,0x6A,0xF4,0xE2,0x3C, - 0x1A,0x94,0x68,0x34,0xB6,0x15,0x0B,0xDA,0x25,0x83,0xE9,0xCA,0x2A,0xD4,0x4C,0xE8, - 0xDB,0xBB,0xC2,0xDB,0x04,0xDE,0x8E,0xF9,0x2E,0x8E,0xFC,0x14,0x1F,0xBE,0xCA,0xA6, - 0x28,0x7C,0x59,0x47,0x4E,0x6B,0xC0,0x5D,0x99,0xB2,0x96,0x4F,0xA0,0x90,0xC3,0xA2, - 0x23,0x3B,0xA1,0x86,0x51,0x5B,0xE7,0xED,0x1F,0x61,0x29,0x70,0xCE,0xE2,0xD7,0xAF, - 0xB8,0x1B,0xDD,0x76,0x21,0x70,0x48,0x1C,0xD0,0x06,0x91,0x27,0xD5,0xB0,0x5A,0xA9, - 0x93,0xB4,0xEA,0x98,0x8D,0x8F,0xDD,0xC1,0x86,0xFF,0xB7,0xDC,0x90,0xA6,0xC0,0x8F, - 0x4D,0xF4,0x35,0xC9,0x34,0x02,0x84,0x92,0x36,0xC3,0xFA,0xB4,0xD2,0x7C,0x70,0x26, - 0xC1,0xD4,0xDC,0xB2,0x60,0x26,0x46,0xDE,0xC9,0x75,0x1E,0x76,0x3D,0xBA,0x37,0xBD, - 0xF8,0xFF,0x94,0x06,0xAD,0x9E,0x53,0x0E,0xE5,0xDB,0x38,0x2F,0x41,0x30,0x01,0xAE, - 0xB0,0x6A,0x53,0xED,0x90,0x27,0xD8,0x31,0x17,0x97,0x27,0xB0,0x86,0x5A,0x89,0x18, - 0xDA,0x3E,0xDB,0xEB,0xCF,0x9B,0x14,0xED,0x44,0xCE,0x6C,0xBA,0xCE,0xD4,0xBB,0x1B, - 0xDB,0x7F,0x14,0x47,0xE6,0xCC,0x25,0x4B,0x33,0x20,0x51,0x51,0x2B,0xD7,0xAF,0x42, - 0x6F,0xB8,0xF4,0x01,0x37,0x8C,0xD2,0xBF,0x59,0x83,0xCA,0x01,0xC6,0x4B,0x92,0xEC, - 0xF0,0x32,0xEA,0x15,0xD1,0x72,0x1D,0x03,0xF4,0x82,0xD7,0xCE,0x6E,0x74,0xFE,0xF6, - 0xD5,0x5E,0x70,0x2F,0x46,0x98,0x0C,0x82,0xB5,0xA8,0x40,0x31,0x90,0x0B,0x1C,0x9E, - 0x59,0xE7,0xC9,0x7F,0xBE,0xC7,0xE8,0xF3,0x23,0xA9,0x7A,0x7E,0x36,0xCC,0x88,0xBE, - 0x0F,0x1D,0x45,0xB7,0xFF,0x58,0x5A,0xC5,0x4B,0xD4,0x07,0xB2,0x2B,0x41,0x54,0xAA, - 0xCC,0x8F,0x6D,0x7E,0xBF,0x48,0xE1,0xD8,0x14,0xCC,0x5E,0xD2,0x0F,0x80,0x37,0xE0, - 0xA7,0x97,0x15,0xEE,0xF2,0x9B,0xE3,0x28,0x06,0xA1,0xD5,0x8B,0xB7,0xC5,0xDA,0x76, - 0xF5,0x50,0xAA,0x3D,0x8A,0x1F,0xBF,0xF0,0xEB,0x19,0xCC,0xB1,0xA3,0x13,0xD5,0x5C, - 0xDA,0x56,0xC9,0xEC,0x2E,0xF2,0x96,0x32,0x38,0x7F,0xE8,0xD7,0x6E,0x3C,0x04,0x68, - 0x04,0x3E,0x8F,0x66,0x3F,0x48,0x60,0xEE,0x12,0xBF,0x2D,0x5B,0x0B,0x74,0x74,0xD6, - 0xE6,0x94,0xF9,0x1E,0x6D,0xCC,0x40,0x24,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF -}; - -/** - * Modulus of Group 18 (MODP_8192_BIT). - */ -static u_int8_t group18_modulus[] = { - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC9,0x0F,0xDA,0xA2,0x21,0x68,0xC2,0x34, - 0xC4,0xC6,0x62,0x8B,0x80,0xDC,0x1C,0xD1,0x29,0x02,0x4E,0x08,0x8A,0x67,0xCC,0x74, - 0x02,0x0B,0xBE,0xA6,0x3B,0x13,0x9B,0x22,0x51,0x4A,0x08,0x79,0x8E,0x34,0x04,0xDD, - 0xEF,0x95,0x19,0xB3,0xCD,0x3A,0x43,0x1B,0x30,0x2B,0x0A,0x6D,0xF2,0x5F,0x14,0x37, - 0x4F,0xE1,0x35,0x6D,0x6D,0x51,0xC2,0x45,0xE4,0x85,0xB5,0x76,0x62,0x5E,0x7E,0xC6, - 0xF4,0x4C,0x42,0xE9,0xA6,0x37,0xED,0x6B,0x0B,0xFF,0x5C,0xB6,0xF4,0x06,0xB7,0xED, - 0xEE,0x38,0x6B,0xFB,0x5A,0x89,0x9F,0xA5,0xAE,0x9F,0x24,0x11,0x7C,0x4B,0x1F,0xE6, - 0x49,0x28,0x66,0x51,0xEC,0xE4,0x5B,0x3D,0xC2,0x00,0x7C,0xB8,0xA1,0x63,0xBF,0x05, - 0x98,0xDA,0x48,0x36,0x1C,0x55,0xD3,0x9A,0x69,0x16,0x3F,0xA8,0xFD,0x24,0xCF,0x5F, - 0x83,0x65,0x5D,0x23,0xDC,0xA3,0xAD,0x96,0x1C,0x62,0xF3,0x56,0x20,0x85,0x52,0xBB, - 0x9E,0xD5,0x29,0x07,0x70,0x96,0x96,0x6D,0x67,0x0C,0x35,0x4E,0x4A,0xBC,0x98,0x04, - 0xF1,0x74,0x6C,0x08,0xCA,0x18,0x21,0x7C,0x32,0x90,0x5E,0x46,0x2E,0x36,0xCE,0x3B, - 0xE3,0x9E,0x77,0x2C,0x18,0x0E,0x86,0x03,0x9B,0x27,0x83,0xA2,0xEC,0x07,0xA2,0x8F, - 0xB5,0xC5,0x5D,0xF0,0x6F,0x4C,0x52,0xC9,0xDE,0x2B,0xCB,0xF6,0x95,0x58,0x17,0x18, - 0x39,0x95,0x49,0x7C,0xEA,0x95,0x6A,0xE5,0x15,0xD2,0x26,0x18,0x98,0xFA,0x05,0x10, - 0x15,0x72,0x8E,0x5A,0x8A,0xAA,0xC4,0x2D,0xAD,0x33,0x17,0x0D,0x04,0x50,0x7A,0x33, - 0xA8,0x55,0x21,0xAB,0xDF,0x1C,0xBA,0x64,0xEC,0xFB,0x85,0x04,0x58,0xDB,0xEF,0x0A, - 0x8A,0xEA,0x71,0x57,0x5D,0x06,0x0C,0x7D,0xB3,0x97,0x0F,0x85,0xA6,0xE1,0xE4,0xC7, - 0xAB,0xF5,0xAE,0x8C,0xDB,0x09,0x33,0xD7,0x1E,0x8C,0x94,0xE0,0x4A,0x25,0x61,0x9D, - 0xCE,0xE3,0xD2,0x26,0x1A,0xD2,0xEE,0x6B,0xF1,0x2F,0xFA,0x06,0xD9,0x8A,0x08,0x64, - 0xD8,0x76,0x02,0x73,0x3E,0xC8,0x6A,0x64,0x52,0x1F,0x2B,0x18,0x17,0x7B,0x20,0x0C, - 0xBB,0xE1,0x17,0x57,0x7A,0x61,0x5D,0x6C,0x77,0x09,0x88,0xC0,0xBA,0xD9,0x46,0xE2, - 0x08,0xE2,0x4F,0xA0,0x74,0xE5,0xAB,0x31,0x43,0xDB,0x5B,0xFC,0xE0,0xFD,0x10,0x8E, - 0x4B,0x82,0xD1,0x20,0xA9,0x21,0x08,0x01,0x1A,0x72,0x3C,0x12,0xA7,0x87,0xE6,0xD7, - 0x88,0x71,0x9A,0x10,0xBD,0xBA,0x5B,0x26,0x99,0xC3,0x27,0x18,0x6A,0xF4,0xE2,0x3C, - 0x1A,0x94,0x68,0x34,0xB6,0x15,0x0B,0xDA,0x25,0x83,0xE9,0xCA,0x2A,0xD4,0x4C,0xE8, - 0xDB,0xBB,0xC2,0xDB,0x04,0xDE,0x8E,0xF9,0x2E,0x8E,0xFC,0x14,0x1F,0xBE,0xCA,0xA6, - 0x28,0x7C,0x59,0x47,0x4E,0x6B,0xC0,0x5D,0x99,0xB2,0x96,0x4F,0xA0,0x90,0xC3,0xA2, - 0x23,0x3B,0xA1,0x86,0x51,0x5B,0xE7,0xED,0x1F,0x61,0x29,0x70,0xCE,0xE2,0xD7,0xAF, - 0xB8,0x1B,0xDD,0x76,0x21,0x70,0x48,0x1C,0xD0,0x06,0x91,0x27,0xD5,0xB0,0x5A,0xA9, - 0x93,0xB4,0xEA,0x98,0x8D,0x8F,0xDD,0xC1,0x86,0xFF,0xB7,0xDC,0x90,0xA6,0xC0,0x8F, - 0x4D,0xF4,0x35,0xC9,0x34,0x02,0x84,0x92,0x36,0xC3,0xFA,0xB4,0xD2,0x7C,0x70,0x26, - 0xC1,0xD4,0xDC,0xB2,0x60,0x26,0x46,0xDE,0xC9,0x75,0x1E,0x76,0x3D,0xBA,0x37,0xBD, - 0xF8,0xFF,0x94,0x06,0xAD,0x9E,0x53,0x0E,0xE5,0xDB,0x38,0x2F,0x41,0x30,0x01,0xAE, - 0xB0,0x6A,0x53,0xED,0x90,0x27,0xD8,0x31,0x17,0x97,0x27,0xB0,0x86,0x5A,0x89,0x18, - 0xDA,0x3E,0xDB,0xEB,0xCF,0x9B,0x14,0xED,0x44,0xCE,0x6C,0xBA,0xCE,0xD4,0xBB,0x1B, - 0xDB,0x7F,0x14,0x47,0xE6,0xCC,0x25,0x4B,0x33,0x20,0x51,0x51,0x2B,0xD7,0xAF,0x42, - 0x6F,0xB8,0xF4,0x01,0x37,0x8C,0xD2,0xBF,0x59,0x83,0xCA,0x01,0xC6,0x4B,0x92,0xEC, - 0xF0,0x32,0xEA,0x15,0xD1,0x72,0x1D,0x03,0xF4,0x82,0xD7,0xCE,0x6E,0x74,0xFE,0xF6, - 0xD5,0x5E,0x70,0x2F,0x46,0x98,0x0C,0x82,0xB5,0xA8,0x40,0x31,0x90,0x0B,0x1C,0x9E, - 0x59,0xE7,0xC9,0x7F,0xBE,0xC7,0xE8,0xF3,0x23,0xA9,0x7A,0x7E,0x36,0xCC,0x88,0xBE, - 0x0F,0x1D,0x45,0xB7,0xFF,0x58,0x5A,0xC5,0x4B,0xD4,0x07,0xB2,0x2B,0x41,0x54,0xAA, - 0xCC,0x8F,0x6D,0x7E,0xBF,0x48,0xE1,0xD8,0x14,0xCC,0x5E,0xD2,0x0F,0x80,0x37,0xE0, - 0xA7,0x97,0x15,0xEE,0xF2,0x9B,0xE3,0x28,0x06,0xA1,0xD5,0x8B,0xB7,0xC5,0xDA,0x76, - 0xF5,0x50,0xAA,0x3D,0x8A,0x1F,0xBF,0xF0,0xEB,0x19,0xCC,0xB1,0xA3,0x13,0xD5,0x5C, - 0xDA,0x56,0xC9,0xEC,0x2E,0xF2,0x96,0x32,0x38,0x7F,0xE8,0xD7,0x6E,0x3C,0x04,0x68, - 0x04,0x3E,0x8F,0x66,0x3F,0x48,0x60,0xEE,0x12,0xBF,0x2D,0x5B,0x0B,0x74,0x74,0xD6, - 0xE6,0x94,0xF9,0x1E,0x6D,0xBE,0x11,0x59,0x74,0xA3,0x92,0x6F,0x12,0xFE,0xE5,0xE4, - 0x38,0x77,0x7C,0xB6,0xA9,0x32,0xDF,0x8C,0xD8,0xBE,0xC4,0xD0,0x73,0xB9,0x31,0xBA, - 0x3B,0xC8,0x32,0xB6,0x8D,0x9D,0xD3,0x00,0x74,0x1F,0xA7,0xBF,0x8A,0xFC,0x47,0xED, - 0x25,0x76,0xF6,0x93,0x6B,0xA4,0x24,0x66,0x3A,0xAB,0x63,0x9C,0x5A,0xE4,0xF5,0x68, - 0x34,0x23,0xB4,0x74,0x2B,0xF1,0xC9,0x78,0x23,0x8F,0x16,0xCB,0xE3,0x9D,0x65,0x2D, - 0xE3,0xFD,0xB8,0xBE,0xFC,0x84,0x8A,0xD9,0x22,0x22,0x2E,0x04,0xA4,0x03,0x7C,0x07, - 0x13,0xEB,0x57,0xA8,0x1A,0x23,0xF0,0xC7,0x34,0x73,0xFC,0x64,0x6C,0xEA,0x30,0x6B, - 0x4B,0xCB,0xC8,0x86,0x2F,0x83,0x85,0xDD,0xFA,0x9D,0x4B,0x7F,0xA2,0xC0,0x87,0xE8, - 0x79,0x68,0x33,0x03,0xED,0x5B,0xDD,0x3A,0x06,0x2B,0x3C,0xF5,0xB3,0xA2,0x78,0xA6, - 0x6D,0x2A,0x13,0xF8,0x3F,0x44,0xF8,0x2D,0xDF,0x31,0x0E,0xE0,0x74,0xAB,0x6A,0x36, - 0x45,0x97,0xE8,0x99,0xA0,0x25,0x5D,0xC1,0x64,0xF3,0x1C,0xC5,0x08,0x46,0x85,0x1D, - 0xF9,0xAB,0x48,0x19,0x5D,0xED,0x7E,0xA1,0xB1,0xD5,0x10,0xBD,0x7E,0xE7,0x4D,0x73, - 0xFA,0xF3,0x6B,0xC3,0x1E,0xCF,0xA2,0x68,0x35,0x90,0x46,0xF4,0xEB,0x87,0x9F,0x92, - 0x40,0x09,0x43,0x8B,0x48,0x1C,0x6C,0xD7,0x88,0x9A,0x00,0x2E,0xD5,0xEE,0x38,0x2B, - 0xC9,0x19,0x0D,0xA6,0xFC,0x02,0x6E,0x47,0x95,0x58,0xE4,0x47,0x56,0x77,0xE9,0xAA, - 0x9E,0x30,0x50,0xE2,0x76,0x56,0x94,0xDF,0xC8,0x1F,0x56,0xE8,0x80,0xB9,0x6E,0x71, - 0x60,0xC9,0x80,0xDD,0x98,0xED,0xD3,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, -}; - -typedef struct modulus_entry_t modulus_entry_t; - -/** - * Entry of the modulus list. - */ -struct modulus_entry_t { - /** - * Group number as it is defined in file transform_substructure.h. - */ - diffie_hellman_group_t group; - - /** - * Pointer to first byte of modulus (network order). - */ - u_int8_t *modulus; - - /* - * Length of modulus in bytes. - */ - size_t modulus_len; - - /* - * Generator value. - */ - u_int16_t generator; -}; - -/** - * All supported modulus values. - */ -static modulus_entry_t modulus_entries[] = { - {MODP_768_BIT, group1_modulus, sizeof(group1_modulus), 2}, - {MODP_1024_BIT, group2_modulus, sizeof(group2_modulus), 2}, - {MODP_1536_BIT, group5_modulus, sizeof(group5_modulus), 2}, - {MODP_2048_BIT, group14_modulus, sizeof(group14_modulus), 2}, - {MODP_3072_BIT, group15_modulus, sizeof(group15_modulus), 2}, - {MODP_4096_BIT, group16_modulus, sizeof(group16_modulus), 2}, - {MODP_6144_BIT, group17_modulus, sizeof(group17_modulus), 2}, - {MODP_8192_BIT, group18_modulus, sizeof(group18_modulus), 2}, -}; - -typedef struct private_diffie_hellman_t private_diffie_hellman_t; - -/** - * Private data of an diffie_hellman_t object. - * - */ -struct private_diffie_hellman_t { - /** - * Public diffie_hellman_t interface. - */ - diffie_hellman_t public; - - /** - * Diffie Hellman group number. - */ - u_int16_t group; - - /* - * Generator value. - */ - mpz_t g; - - /** - * My private value. - */ - mpz_t xa; - - /** - * My public value. - */ - mpz_t ya; - - /** - * Other public value. - */ - mpz_t yb; - - /** - * Shared secret. - */ - mpz_t zz; - - /** - * Modulus. - */ - mpz_t p; - - /** - * Modulus length. - */ - size_t p_len; - - /** - * True if shared secret is computed and stored in my_public_value. - */ - bool computed; -}; - -/** - * Implementation of diffie_hellman_t.set_other_public_value. - */ -static void set_other_public_value(private_diffie_hellman_t *this, chunk_t value) -{ - mpz_t p_min_1; - - mpz_init(p_min_1); - mpz_sub_ui(p_min_1, this->p, 1); - - mpz_import(this->yb, value.len, 1, 1, 1, 0, value.ptr); - - /* check public value: - * 1. 0 or 1 is invalid as 0^a = 0 and 1^a = 1 - * 2. a public value larger or equal the modulus is invalid */ - if (mpz_cmp_ui(this->yb, 1) > 0 || - mpz_cmp(this->yb, p_min_1) < 0) - { -#ifdef EXTENDED_DH_TEST - /* 3. test if y ^ q mod p = 1, where q = (p - 1)/2. */ - mpz_t q, one; - - mpz_init(q); - mpz_init(one); - mpz_fdiv_q_2exp(q, p_min_1, 1); - mpz_powm(one, this->yb, q, this->p); - mpz_clear(q); - if (mpz_cmp_ui(one, 1) == 0) - { - mpz_powm(this->zz, this->yb, this->xa, this->p); - this->computed = TRUE; - } - else - { - DBG1("public DH value verification failed: y ^ q mod p != 1"); - } - mpz_clear(one); -#else - mpz_powm(this->zz, this->yb, this->xa, this->p); - this->computed = TRUE; -#endif - } - else - { - DBG1("public DH value verification failed: y < 2 || y > p - 1 "); - } - mpz_clear(p_min_1); -} - -/** - * Implementation of diffie_hellman_t.get_other_public_value. - */ -static status_t get_other_public_value(private_diffie_hellman_t *this, - chunk_t *value) -{ - if (!this->computed) - { - return FAILED; - } - value->len = this->p_len; - value->ptr = mpz_export(NULL, NULL, 1, value->len, 1, 0, this->yb); - return SUCCESS; -} - -/** - * Implementation of diffie_hellman_t.get_my_public_value. - */ -static void get_my_public_value(private_diffie_hellman_t *this,chunk_t *value) -{ - value->len = this->p_len; - value->ptr = mpz_export(NULL, NULL, 1, value->len, 1, 0, this->ya); -} - -/** - * Implementation of diffie_hellman_t.get_shared_secret. - */ -static status_t get_shared_secret(private_diffie_hellman_t *this, chunk_t *secret) -{ - if (!this->computed) - { - return FAILED; - } - secret->len = this->p_len; - secret->ptr = mpz_export(NULL, NULL, 1, secret->len, 1, 0, this->zz); - return SUCCESS; -} - -/** - * Implementation of diffie_hellman_t.get_dh_group. - */ -static diffie_hellman_group_t get_dh_group(private_diffie_hellman_t *this) -{ - return this->group; -} - -/** - * Lookup the modulus in modulo table - */ -static status_t set_modulus(private_diffie_hellman_t *this) -{ - int i; - status_t status = NOT_FOUND; - - for (i = 0; i < (sizeof(modulus_entries) / sizeof(modulus_entry_t)); i++) - { - if (modulus_entries[i].group == this->group) - { - chunk_t chunk; - chunk.ptr = modulus_entries[i].modulus; - chunk.len = modulus_entries[i].modulus_len; - mpz_import(this->p, chunk.len, 1, 1, 1, 0, chunk.ptr); - this->p_len = chunk.len; - mpz_set_ui(this->g, modulus_entries[i].generator); - status = SUCCESS; - break; - } - } - return status; -} - -/** - * Implementation of diffie_hellman_t.destroy. - */ -static void destroy(private_diffie_hellman_t *this) -{ - mpz_clear(this->p); - mpz_clear(this->xa); - mpz_clear(this->ya); - mpz_clear(this->yb); - mpz_clear(this->zz); - mpz_clear(this->g); - free(this); -} - -/* - * Described in header. - */ -diffie_hellman_t *diffie_hellman_create(diffie_hellman_group_t group) -{ - private_diffie_hellman_t *this = malloc_thing(private_diffie_hellman_t); - randomizer_t *randomizer; - chunk_t random; - status_t status; - - /* public functions */ - this->public.get_shared_secret = (status_t (*)(diffie_hellman_t *, chunk_t *)) get_shared_secret; - this->public.set_other_public_value = (void (*)(diffie_hellman_t *, chunk_t )) set_other_public_value; - this->public.get_other_public_value = (status_t (*)(diffie_hellman_t *, chunk_t *)) get_other_public_value; - this->public.get_my_public_value = (void (*)(diffie_hellman_t *, chunk_t *)) get_my_public_value; - this->public.get_dh_group = (diffie_hellman_group_t (*)(diffie_hellman_t *)) get_dh_group; - this->public.destroy = (void (*)(diffie_hellman_t *)) destroy; - - /* private variables */ - this->group = group; - mpz_init(this->p); - mpz_init(this->yb); - mpz_init(this->ya); - mpz_init(this->xa); - mpz_init(this->zz); - mpz_init(this->g); - - this->computed = FALSE; - - /* find a modulus according to group */ - if (set_modulus(this) != SUCCESS) - { - destroy(this); - return NULL; - } - randomizer = randomizer_create(); - status = randomizer->allocate_pseudo_random_bytes( - randomizer, this->p_len, &random); - randomizer->destroy(randomizer); - if (status != SUCCESS) - { - destroy(this); - return NULL; - } - mpz_import(this->xa, random.len, 1, 1, 1, 0, random.ptr); - chunk_free(&random); - - mpz_powm(this->ya, this->g, this->xa, this->p); - - return &this->public; -} + "MODP_8192_BIT", + "ECP_256_BIT", + "ECP_384_BIT", + "ECP_521_BIT"); +ENUM_NEXT(diffie_hellman_group_names, ECP_192_BIT, ECP_224_BIT, ECP_521_BIT, + "ECP_192_BIT", + "ECP_224_BIT"); +ENUM_END(diffie_hellman_group_names, ECP_224_BIT); diff --git a/src/libstrongswan/crypto/diffie_hellman.h b/src/libstrongswan/crypto/diffie_hellman.h index 8cd06d60e..c66ae56c3 100644 --- a/src/libstrongswan/crypto/diffie_hellman.h +++ b/src/libstrongswan/crypto/diffie_hellman.h @@ -1,10 +1,3 @@ -/** - * @file diffie_hellman.h - * - * @brief Interface of diffie_hellman_t. - * - */ - /* * Copyright (C) 2005-2007 Martin Willi * Copyright (C) 2005 Jan Hutter @@ -19,6 +12,13 @@ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. + * + * $Id: diffie_hellman.h 4023 2008-05-29 06:55:03Z andreas $ + */ + +/** + * @defgroup diffie_hellman diffie_hellman + * @{ @ingroup crypto */ #ifndef DIFFIE_HELLMAN_H_ @@ -30,24 +30,28 @@ typedef struct diffie_hellman_t diffie_hellman_t; #include <library.h> /** - * @brief Diffie-Hellman group. + * Diffie-Hellman group. * * The modulus (or group) to use for a Diffie-Hellman calculation. - * * See IKEv2 RFC 3.3.2 and RFC 3526. - * - * @ingroup crypto + * + * ECP groups are defined in RFC 4753 and RFC 5114. */ enum diffie_hellman_group_t { - MODP_NONE = 0, - MODP_768_BIT = 1, - MODP_1024_BIT = 2, - MODP_1536_BIT = 5, + MODP_NONE = 0, + MODP_768_BIT = 1, + MODP_1024_BIT = 2, + MODP_1536_BIT = 5, MODP_2048_BIT = 14, MODP_3072_BIT = 15, MODP_4096_BIT = 16, MODP_6144_BIT = 17, - MODP_8192_BIT = 18 + MODP_8192_BIT = 18, + ECP_256_BIT = 19, + ECP_384_BIT = 20, + ECP_521_BIT = 21, + ECP_192_BIT = 25, + ECP_224_BIT = 26, }; /** @@ -56,89 +60,60 @@ enum diffie_hellman_group_t { extern enum_name_t *diffie_hellman_group_names; /** - * @brief Implementation of the Diffie-Hellman algorithm, as in RFC2631. - * - * @b Constructors: - * - diffie_hellman_create() - * - * @ingroup crypto + * Implementation of the Diffie-Hellman algorithm, as in RFC2631. */ struct diffie_hellman_t { /** - * @brief Returns the shared secret of this diffie hellman exchange. + * Returns the shared secret of this diffie hellman exchange. * * Space for returned secret is allocated and must be * freed by the caller. * - * @param this calling object * @param secret shared secret will be written into this chunk - * @return - * - SUCCESS - * - FAILED if not both DH values are set + * @return SUCCESS, FAILED if not both DH values are set */ status_t (*get_shared_secret) (diffie_hellman_t *this, chunk_t *secret); /** - * @brief Sets the public value of partner. + * Sets the public value of partner. * * Chunk gets cloned and can be destroyed afterwards. * - * @param this calling object * @param value public value of partner */ void (*set_other_public_value) (diffie_hellman_t *this, chunk_t value); /** - * @brief Gets the public value of partner. + * Gets the public value of partner. * * Space for returned chunk is allocated and must be freed by the caller. * - * @param this calling object * @param value public value of partner is stored at this location - * @return - * - SUCCESS - * - FAILED if other public value not set + * @return SUCCESS, FAILED if other public value not set */ status_t (*get_other_public_value) (diffie_hellman_t *this, chunk_t *value); /** - * @brief Gets the own public value to transmit. + * Gets the own public value to transmit. * * Space for returned chunk is allocated and must be freed by the caller. * - * @param this calling object * @param value public value of caller is stored at this location */ void (*get_my_public_value) (diffie_hellman_t *this, chunk_t *value); /** - * @brief Get the DH group used. + * Get the DH group used. * - * @param this calling object * @return DH group set in construction */ diffie_hellman_group_t (*get_dh_group) (diffie_hellman_t *this); /** - * @brief Destroys an diffie_hellman_t object. - * - * @param this diffie_hellman_t object to destroy + * Destroys an diffie_hellman_t object. */ void (*destroy) (diffie_hellman_t *this); }; -/** - * @brief Creates a new diffie_hellman_t object. - * - * @param group Diffie Hellman group number to use - * @return - * - diffie_hellman_t object - * - NULL if dh group not supported - * - * @ingroup crypto - */ -diffie_hellman_t *diffie_hellman_create(diffie_hellman_group_t group); - -#endif /*DIFFIE_HELLMAN_H_*/ - +#endif /*DIFFIE_HELLMAN_H_ @} */ diff --git a/src/libstrongswan/crypto/hashers/hasher.c b/src/libstrongswan/crypto/hashers/hasher.c index 9fa778aa6..6c29d1d5d 100644 --- a/src/libstrongswan/crypto/hashers/hasher.c +++ b/src/libstrongswan/crypto/hashers/hasher.c @@ -1,10 +1,3 @@ -/** - * @file hasher.c - * - * @brief Generic constructor for hasher_t. - * - */ - /* * Copyright (C) 2005 Jan Hutter * Copyright (C) 2005-2006 Martin Willi @@ -21,20 +14,16 @@ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * - * RCSID $Id: hasher.c 3423 2008-01-22 10:32:37Z andreas $ + * $Id: hasher.c 3619 2008-03-19 14:02:52Z martin $ */ - #include "hasher.h" #include <asn1/oid.h> -#include <crypto/hashers/sha1_hasher.h> -#include <crypto/hashers/sha2_hasher.h> -#include <crypto/hashers/md5_hasher.h> - ENUM(hash_algorithm_names, HASH_UNKNOWN, HASH_SHA512, "HASH_UNKNOWN", + "HASH_PREFERRED", "HASH_MD2", "HASH_MD5", "HASH_SHA1", @@ -46,66 +35,31 @@ ENUM(hash_algorithm_names, HASH_UNKNOWN, HASH_SHA512, /* * Described in header. */ -hasher_t *hasher_create(hash_algorithm_t hash_algorithm) -{ - switch (hash_algorithm) - { - case HASH_SHA1: - { - return (hasher_t*)sha1_hasher_create(); - } - case HASH_SHA256: - case HASH_SHA384: - case HASH_SHA512: - { - return (hasher_t*)sha2_hasher_create(hash_algorithm); - } - case HASH_MD5: - { - return (hasher_t*)md5_hasher_create(); - } - default: - return NULL; - } -} - -/* - * Described in header. - */ hash_algorithm_t hasher_algorithm_from_oid(int oid) { - hash_algorithm_t algorithm; - switch (oid) { case OID_MD2: case OID_MD2_WITH_RSA: - algorithm = HASH_MD2; - break; + return HASH_MD2; case OID_MD5: case OID_MD5_WITH_RSA: - algorithm = HASH_MD5; - break; + return HASH_MD5; case OID_SHA1: case OID_SHA1_WITH_RSA: - algorithm = HASH_SHA1; - break; + return HASH_SHA1; case OID_SHA256: case OID_SHA256_WITH_RSA: - algorithm = HASH_SHA256; - break; + return HASH_SHA256; case OID_SHA384: case OID_SHA384_WITH_RSA: - algorithm = HASH_SHA384; - break; + return HASH_SHA384; case OID_SHA512: case OID_SHA512_WITH_RSA: - algorithm = HASH_SHA512; - break; + return HASH_SHA512; default: - algorithm = HASH_UNKNOWN; + return HASH_UNKNOWN; } - return algorithm; } /* diff --git a/src/libstrongswan/crypto/hashers/hasher.h b/src/libstrongswan/crypto/hashers/hasher.h index e73de7f01..e19b0318b 100644 --- a/src/libstrongswan/crypto/hashers/hasher.h +++ b/src/libstrongswan/crypto/hashers/hasher.h @@ -1,10 +1,3 @@ -/** - * @file hasher.h - * - * @brief Interface hasher_t. - * - */ - /* * Copyright (C) 2005 Jan Hutter * Copyright (C) 2005-2006 Martin Willi @@ -21,7 +14,12 @@ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * - * RCSID $Id: hasher.h 3423 2008-01-22 10:32:37Z andreas $ + * $Id: hasher.h 3619 2008-03-19 14:02:52Z martin $ + */ + +/** + * @defgroup traffic_selector traffic_selector + * @{ @ingroup config */ #ifndef HASHER_H_ @@ -33,30 +31,19 @@ typedef struct hasher_t hasher_t; #include <library.h> /** - * @brief Algorithms to use for hashing. - * - * Currently only the following algorithms are implemented: - * - HASH_MD5 - * - HASH_SHA1 - * - HASH_SHA256 - * - HASH_SHA384 - * - HASH_SHA512 - * - * @ingroup hashers + * Algorithms to use for hashing. */ enum hash_algorithm_t { - HASH_UNKNOWN = 0, - HASH_MD2 = 1, - /** Implemented in class md5_hasher_t */ - HASH_MD5 = 2, - /** Implemented in class sha1_hasher_t */ - HASH_SHA1 = 3, - /** Implemented in class sha2_hasher_t */ - HASH_SHA256 = 4, - /** Implemented in class sha2_hasher_t */ - HASH_SHA384 = 5, - /** Implemented in class sha2_hasher_t */ - HASH_SHA512 = 6, + /** not specified hash function */ + HASH_UNKNOWN = 0, + /** preferred hash function, general purpose */ + HASH_PREFERRED = 1, + HASH_MD2 = 2, + HASH_MD5 = 3, + HASH_SHA1 = 4, + HASH_SHA256 = 5, + HASH_SHA384 = 6, + HASH_SHA512 = 7, }; #define HASH_SIZE_MD2 16 @@ -65,7 +52,6 @@ enum hash_algorithm_t { #define HASH_SIZE_SHA256 32 #define HASH_SIZE_SHA384 48 #define HASH_SIZE_SHA512 64 -#define HASH_SIZE_MAX 64 /** * enum names for hash_algorithm_t. @@ -73,16 +59,11 @@ enum hash_algorithm_t { extern enum_name_t *hash_algorithm_names; /** - * @brief Generic interface for all hash functions. - * - * @b Constructors: - * - hasher_create() - * - * @ingroup hashers + * Generic interface for all hash functions. */ struct hasher_t { /** - * @brief Hash data and write it in the buffer. + * Hash data and write it in the buffer. * * If the parameter hash is NULL, no result is written back * and more data can be appended to already hashed data. @@ -91,108 +72,63 @@ struct hasher_t { * The hash output parameter must hold at least * hash_t.get_block_size() bytes. * - * @param this calling object - * @param data data to hash - * @param[out] hash pointer where the hash will be written + * @param data data to hash + * @param hash pointer where the hash will be written */ void (*get_hash) (hasher_t *this, chunk_t data, u_int8_t *hash); /** - * @brief Hash data and allocate space for the hash. + * Hash data and allocate space for the hash. * * If the parameter hash is NULL, no result is written back * and more data can be appended to already hashed data. * If not, the result is written back and the hasher is reset. * - * @param this calling object - * @param data chunk with data to hash - * @param[out] hash chunk which will hold allocated hash + * @param data chunk with data to hash + * @param hash chunk which will hold allocated hash */ void (*allocate_hash) (hasher_t *this, chunk_t data, chunk_t *hash); /** - * @brief Get the size of the resulting hash. + * Get the size of the resulting hash. * - * @param this calling object - * @return hash size in bytes + * @return hash size in bytes */ size_t (*get_hash_size) (hasher_t *this); /** - * @brief Resets the hashers state. - * - * @param this calling object + * Resets the hashers state. */ void (*reset) (hasher_t *this); /** - * @brief Get the state of the hasher. - * - * A hasher stores internal state information. This state may be - * manipulated to include a "seed" into the hashing operation. It used by - * some exotic protocols (such as AKA). - * The data pointed by chunk may be manipulated, but not replaced nor freed. - * This is more a hack than a feature. The hasher's state may be byte - * order dependant; use with care. - * - * @param this calling object - */ - chunk_t (*get_state) (hasher_t *this); - - /** - * @brief Destroys a hasher object. - * - * @param this calling object + * Destroys a hasher object. */ void (*destroy) (hasher_t *this); }; /** - * @brief Generic interface to create a hasher_t. + * Conversion of ASN.1 OID to hash algorithm. * - * @param hash_algorithm Algorithm to use for hashing - * @return - * - hasher_t object - * - NULL if algorithm not supported - * - * @ingroup hashers - */ -hasher_t *hasher_create(hash_algorithm_t hash_algorithm); - -/** - * @brief Conversion of ASN.1 OID to hash algorithm. - * - * @param oid ASN.1 OID - * @return - * - hash algorithm - * - HASH_UNKNOWN if OID unsuported - * - * @ingroup hashers + * @param oid ASN.1 OID + * @return hash algorithm, HASH_UNKNOWN if OID unsuported */ hash_algorithm_t hasher_algorithm_from_oid(int oid); /** - * @brief Conversion of hash algorithm into ASN.1 OID. + * Conversion of hash algorithm into ASN.1 OID. * - * @param alg hash algorithm - * @return - * - ASN.1 hash OID if known hash algorithm - * - OID_UNKNOW - * - * @ingroup hashers + * @param alg hash algorithm + * @return ASN.1 OID, or OID_UNKNOW */ int hasher_algorithm_to_oid(hash_algorithm_t alg); /** - * @brief Conversion of hash signature algorithm into ASN.1 OID. - * - * @param alg hash algorithm - * @return - * - ASN.1 signature OID if known hash algorithm - * - OID_UNKNOW + * Conversion of hash signature algorithm into ASN.1 OID. * - * @ingroup hashers + * @param alg hash algorithm + * @return ASN.1 OID if, or OID_UNKNOW */ int hasher_signature_algorithm_to_oid(hash_algorithm_t alg); -#endif /* HASHER_H_ */ +#endif /* HASHER_H_ @} */ diff --git a/src/libstrongswan/crypto/hashers/md5_hasher.c b/src/libstrongswan/crypto/hashers/md5_hasher.c deleted file mode 100644 index d4dde3693..000000000 --- a/src/libstrongswan/crypto/hashers/md5_hasher.c +++ /dev/null @@ -1,405 +0,0 @@ -/** - * @file md5_hasher.c - * - * @brief Implementation of md5_hasher_t. - * - */ - -/* - * Copyright (C) 2005-2006 Martin Willi - * Copyright (C) 2005 Jan Hutter - * Hochschule fuer Technik Rapperswil - * Copyright (C) 1991-1992, RSA Data Security, Inc. Created 1991. - * All rights reserved. - * - * Derived from the RSA Data Security, Inc. MD5 Message-Digest Algorithm. - * Ported to fulfill hasher_t interface. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -#include <string.h> - -#include "md5_hasher.h" - - -/* Constants for MD5Transform routine. */ -#define S11 7 -#define S12 12 -#define S13 17 -#define S14 22 -#define S21 5 -#define S22 9 -#define S23 14 -#define S24 20 -#define S31 4 -#define S32 11 -#define S33 16 -#define S34 23 -#define S41 6 -#define S42 10 -#define S43 15 -#define S44 21 - -static u_int8_t PADDING[64] = { - 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 -}; - -/* - * ugly macro stuff - */ -/* F, G, H and I are basic MD5 functions. - */ -#define F(x, y, z) (((x) & (y)) | ((~x) & (z))) -#define G(x, y, z) (((x) & (z)) | ((y) & (~z))) -#define H(x, y, z) ((x) ^ (y) ^ (z)) -#define I(x, y, z) ((y) ^ ((x) | (~z))) - -/* ROTATE_LEFT rotates x left n bits. - */ -#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n)))) - -/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4. -Rotation is separate from addition to prevent recomputation. - */ -#define FF(a, b, c, d, x, s, ac) { \ - (a) += F ((b), (c), (d)) + (x) + (u_int32_t)(ac); \ - (a) = ROTATE_LEFT ((a), (s)); \ - (a) += (b); \ - } -#define GG(a, b, c, d, x, s, ac) { \ - (a) += G ((b), (c), (d)) + (x) + (u_int32_t)(ac); \ - (a) = ROTATE_LEFT ((a), (s)); \ - (a) += (b); \ - } -#define HH(a, b, c, d, x, s, ac) { \ - (a) += H ((b), (c), (d)) + (x) + (u_int32_t)(ac); \ - (a) = ROTATE_LEFT ((a), (s)); \ - (a) += (b); \ - } -#define II(a, b, c, d, x, s, ac) { \ - (a) += I ((b), (c), (d)) + (x) + (u_int32_t)(ac); \ - (a) = ROTATE_LEFT ((a), (s)); \ - (a) += (b); \ - } - - - -typedef struct private_md5_hasher_t private_md5_hasher_t; - -/** - * Private data structure with hasing context. - */ -struct private_md5_hasher_t { - /** - * Public interface for this hasher. - */ - md5_hasher_t public; - - /* - * State of the hasher. - */ - u_int32_t state[5]; - u_int32_t count[2]; - u_int8_t buffer[64]; -}; - - -#if BYTE_ORDER != LITTLE_ENDIAN - -/* Encodes input (u_int32_t) into output (u_int8_t). Assumes len is - * a multiple of 4. - */ -static void Encode (u_int8_t *output, u_int32_t *input, size_t len) -{ - size_t i, j; - - for (i = 0, j = 0; j < len; i++, j += 4) - { - output[j] = (u_int8_t)(input[i] & 0xff); - output[j+1] = (u_int8_t)((input[i] >> 8) & 0xff); - output[j+2] = (u_int8_t)((input[i] >> 16) & 0xff); - output[j+3] = (u_int8_t)((input[i] >> 24) & 0xff); - } -} - -/* Decodes input (u_int8_t) into output (u_int32_t). Assumes len is - * a multiple of 4. - */ -static void Decode(u_int32_t *output, u_int8_t *input, size_t len) -{ - size_t i, j; - - for (i = 0, j = 0; j < len; i++, j += 4) - { - output[i] = ((u_int32_t)input[j]) | (((u_int32_t)input[j+1]) << 8) | - (((u_int32_t)input[j+2]) << 16) | (((u_int32_t)input[j+3]) << 24); - } -} - -#elif BYTE_ORDER == LITTLE_ENDIAN - #define Encode memcpy - #define Decode memcpy -#endif - -/* MD5 basic transformation. Transforms state based on block. - */ -static void MD5Transform(u_int32_t state[4], u_int8_t block[64]) -{ - u_int32_t a = state[0], b = state[1], c = state[2], d = state[3], x[16]; - - Decode(x, block, 64); - - /* Round 1 */ - FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */ - FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */ - FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */ - FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */ - FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */ - FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */ - FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */ - FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */ - FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */ - FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */ - FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */ - FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */ - FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */ - FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */ - FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */ - FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */ - - /* Round 2 */ - GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */ - GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */ - GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */ - GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */ - GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */ - GG (d, a, b, c, x[10], S22, 0x2441453); /* 22 */ - GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */ - GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */ - GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */ - GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */ - GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */ - GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */ - GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */ - GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */ - GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */ - GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */ - - /* Round 3 */ - HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */ - HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */ - HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */ - HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */ - HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */ - HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */ - HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */ - HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */ - HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */ - HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */ - HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */ - HH (b, c, d, a, x[ 6], S34, 0x4881d05); /* 44 */ - HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */ - HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */ - HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */ - HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */ - - /* Round 4 */ - II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */ - II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */ - II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */ - II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */ - II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */ - II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */ - II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */ - II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */ - II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */ - II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */ - II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */ - II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */ - II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */ - II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */ - II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */ - II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */ - - state[0] += a; - state[1] += b; - state[2] += c; - state[3] += d; -} - -/* MD5 block update operation. Continues an MD5 message-digest - * operation, processing another message block, and updating the - * context. - */ -static void MD5Update(private_md5_hasher_t *this, u_int8_t *input, size_t inputLen) -{ - u_int32_t i; - size_t index, partLen; - - /* Compute number of bytes mod 64 */ - index = (u_int8_t)((this->count[0] >> 3) & 0x3F); - - /* Update number of bits */ - if ((this->count[0] += (inputLen << 3)) < (inputLen << 3)) - { - this->count[1]++; - } - this->count[1] += (inputLen >> 29); - - partLen = 64 - index; - - /* Transform as many times as possible. */ - if (inputLen >= partLen) - { - memcpy(&this->buffer[index], input, partLen); - MD5Transform (this->state, this->buffer); - - for (i = partLen; i + 63 < inputLen; i += 64) - { - MD5Transform (this->state, &input[i]); - } - index = 0; - } - else - { - i = 0; - } - - /* Buffer remaining input */ - memcpy(&this->buffer[index], &input[i], inputLen-i); -} - -/* MD5 finalization. Ends an MD5 message-digest operation, writing the - * the message digest and zeroizing the context. - */ -static void MD5Final (private_md5_hasher_t *this, u_int8_t digest[16]) -{ - u_int8_t bits[8]; - size_t index, padLen; - - /* Save number of bits */ - Encode (bits, this->count, 8); - - /* Pad out to 56 mod 64. */ - index = (size_t)((this->count[0] >> 3) & 0x3f); - padLen = (index < 56) ? (56 - index) : (120 - index); - MD5Update (this, PADDING, padLen); - - /* Append length (before padding) */ - MD5Update (this, bits, 8); - - if (digest != NULL) /* Bill Simpson's padding */ - { - /* store state in digest */ - Encode (digest, this->state, 16); - } -} - - - -/** - * Implementation of hasher_t.get_hash. - */ -static void get_hash(private_md5_hasher_t *this, chunk_t chunk, u_int8_t *buffer) -{ - MD5Update(this, chunk.ptr, chunk.len); - if (buffer != NULL) - { - MD5Final(this, buffer); - this->public.hasher_interface.reset(&(this->public.hasher_interface)); - } -} - - -/** - * Implementation of hasher_t.allocate_hash. - */ -static void allocate_hash(private_md5_hasher_t *this, chunk_t chunk, chunk_t *hash) -{ - chunk_t allocated_hash; - - MD5Update(this, chunk.ptr, chunk.len); - if (hash != NULL) - { - allocated_hash.ptr = malloc(HASH_SIZE_MD5); - allocated_hash.len = HASH_SIZE_MD5; - - MD5Final(this, allocated_hash.ptr); - this->public.hasher_interface.reset(&(this->public.hasher_interface)); - - *hash = allocated_hash; - } -} - -/** - * Implementation of hasher_t.get_hash_size. - */ -static size_t get_hash_size(private_md5_hasher_t *this) -{ - return HASH_SIZE_MD5; -} - -/** - * Implementation of hasher_t.reset. - */ -static void reset(private_md5_hasher_t *this) -{ - this->state[0] = 0x67452301; - this->state[1] = 0xefcdab89; - this->state[2] = 0x98badcfe; - this->state[3] = 0x10325476; - this->count[0] = 0; - this->count[1] = 0; -} - -/** - * Implementation of hasher_t.get_state - */ -static chunk_t get_state(private_md5_hasher_t *this) -{ - chunk_t chunk; - - chunk.ptr = (u_char*)&this->state[0]; - chunk.len = sizeof(this->state); - - return chunk; -} - -/** - * Implementation of hasher_t.destroy. - */ -static void destroy(private_md5_hasher_t *this) -{ - free(this); -} - -/* - * Described in header. - */ -md5_hasher_t *md5_hasher_create(void) -{ - private_md5_hasher_t *this = malloc_thing(private_md5_hasher_t); - - this->public.hasher_interface.get_hash = (void (*) (hasher_t*, chunk_t, u_int8_t*))get_hash; - this->public.hasher_interface.allocate_hash = (void (*) (hasher_t*, chunk_t, chunk_t*))allocate_hash; - this->public.hasher_interface.get_hash_size = (size_t (*) (hasher_t*))get_hash_size; - this->public.hasher_interface.reset = (void (*) (hasher_t*))reset; - this->public.hasher_interface.get_state = (chunk_t (*) (hasher_t*))get_state; - this->public.hasher_interface.destroy = (void (*) (hasher_t*))destroy; - - /* initialize */ - reset(this); - - return &(this->public); -} diff --git a/src/libstrongswan/crypto/hashers/md5_hasher.h b/src/libstrongswan/crypto/hashers/md5_hasher.h deleted file mode 100644 index 715f11663..000000000 --- a/src/libstrongswan/crypto/hashers/md5_hasher.h +++ /dev/null @@ -1,60 +0,0 @@ -/** - * @file md5_hasher.h - * - * @brief Interface for md5_hasher_t. - * - */ - -/* - * Copyright (C) 2005-2006 Martin Willi - * Copyright (C) 2005 Jan Hutter - * Hochschule fuer Technik Rapperswil - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -#ifndef MD5_HASHER_H_ -#define MD5_HASHER_H_ - -typedef struct md5_hasher_t md5_hasher_t; - -#include <crypto/hashers/hasher.h> - -/** - * @brief Implementation of hasher_t interface using the - * MD5 algorithm. - * - * @b Constructors: - * - hasher_create() using HASH_MD5 as algorithm - * - md5_hasher_create() - * - * @see hasher_t - * - * @ingroup hashers - */ -struct md5_hasher_t { - - /** - * Generic hasher_t interface for this hasher. - */ - hasher_t hasher_interface; -}; - -/** - * @brief Creates a new md5_hasher_t. - * - * @return md5_hasher_t object - * - * @ingroup hashers - */ -md5_hasher_t *md5_hasher_create(void); - -#endif /*MD5_HASHER_H_*/ diff --git a/src/libstrongswan/crypto/hashers/sha1_hasher.c b/src/libstrongswan/crypto/hashers/sha1_hasher.c deleted file mode 100644 index 6a86937ae..000000000 --- a/src/libstrongswan/crypto/hashers/sha1_hasher.c +++ /dev/null @@ -1,280 +0,0 @@ -/** - * @file sha1_hasher.c - * - * @brief Implementation of hasher_sha_t. - * - */ - -/* - * Copyright (C) 2005-2006 Martin Willi - * Copyright (C) 2005 Jan Hutter - * Hochschule fuer Technik Rapperswil - * - * Ported from Steve Reid's <steve@edmweb.com> implementation - * "SHA1 in C" found in strongSwan. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -#include <string.h> - -#include "sha1_hasher.h" - -/* - * ugly macro stuff - */ -#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits)))) - -#if BYTE_ORDER == LITTLE_ENDIAN - #define blk0(i) (block->l[i] = (rol(block->l[i],24)&0xFF00FF00) |(rol(block->l[i],8)&0x00FF00FF)) -#elif BYTE_ORDER == BIG_ENDIAN - #define blk0(i) block->l[i] -#else - #error "Endianness not defined!" -#endif -#define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] ^block->l[(i+2)&15]^block->l[i&15],1)) - -/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */ -#define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30); -#define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30); -#define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30); -#define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30); -#define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30); - - -typedef struct private_sha1_hasher_t private_sha1_hasher_t; - -/** - * Private data structure with hasing context. - */ -struct private_sha1_hasher_t { - /** - * Public interface for this hasher. - */ - sha1_hasher_t public; - - /* - * State of the hasher. - */ - u_int32_t state[5]; - u_int32_t count[2]; - u_int8_t buffer[64]; -}; - -/* - * Hash a single 512-bit block. This is the core of the algorithm. * - */ -static void SHA1Transform(u_int32_t state[5], const unsigned char buffer[64]) -{ - u_int32_t a, b, c, d, e; - typedef union { - u_int8_t c[64]; - u_int32_t l[16]; - } CHAR64LONG16; - CHAR64LONG16 block[1]; /* use array to appear as a pointer */ - memcpy(block, buffer, 64); - - /* Copy context->state[] to working vars */ - a = state[0]; - b = state[1]; - c = state[2]; - d = state[3]; - e = state[4]; - /* 4 rounds of 20 operations each. Loop unrolled. */ - R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3); - R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7); - R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11); - R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15); - R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19); - R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23); - R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27); - R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31); - R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35); - R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39); - R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43); - R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47); - R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51); - R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55); - R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59); - R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63); - R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67); - R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71); - R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75); - R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79); - /* Add the working vars back into context.state[] */ - state[0] += a; - state[1] += b; - state[2] += c; - state[3] += d; - state[4] += e; - /* Wipe variables */ - a = b = c = d = e = 0; - memset(block, '\0', sizeof(block)); -} - -/* - * Run your data through this. - */ -static void SHA1Update(private_sha1_hasher_t* this, u_int8_t *data, u_int32_t len) -{ - u_int32_t i; - u_int32_t j; - - j = this->count[0]; - if ((this->count[0] += len << 3) < j) - { - this->count[1]++; - } - this->count[1] += (len>>29); - j = (j >> 3) & 63; - if ((j + len) > 63) - { - memcpy(&this->buffer[j], data, (i = 64-j)); - SHA1Transform(this->state, this->buffer); - for ( ; i + 63 < len; i += 64) - { - SHA1Transform(this->state, &data[i]); - } - j = 0; - } - else - { - i = 0; - } - memcpy(&this->buffer[j], &data[i], len - i); -} - - -/* - * Add padding and return the message digest. - */ -static void SHA1Final(private_sha1_hasher_t *this, u_int8_t *digest) -{ - u_int32_t i; - u_int8_t finalcount[8]; - u_int8_t c; - - for (i = 0; i < 8; i++) - { - finalcount[i] = (u_int8_t)((this->count[(i >= 4 ? 0 : 1)] - >> ((3-(i & 3)) * 8) ) & 255); /* Endian independent */ - } - c = 0200; - SHA1Update(this, &c, 1); - while ((this->count[0] & 504) != 448) - { - c = 0000; - SHA1Update(this, &c, 1); - } - SHA1Update(this, finalcount, 8); /* Should cause a SHA1Transform() */ - for (i = 0; i < 20; i++) - { - digest[i] = (u_int8_t)((this->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255); - } -} - - -/** - * Implementation of hasher_t.get_hash. - */ -static void get_hash(private_sha1_hasher_t *this, chunk_t chunk, u_int8_t *buffer) -{ - SHA1Update(this, chunk.ptr, chunk.len); - if (buffer != NULL) - { - SHA1Final(this, buffer); - this->public.hasher_interface.reset(&(this->public.hasher_interface)); - } -} - - -/** - * Implementation of hasher_t.allocate_hash. - */ -static void allocate_hash(private_sha1_hasher_t *this, chunk_t chunk, chunk_t *hash) -{ - chunk_t allocated_hash; - - SHA1Update(this, chunk.ptr, chunk.len); - if (hash != NULL) - { - allocated_hash.ptr = malloc(HASH_SIZE_SHA1); - allocated_hash.len = HASH_SIZE_SHA1; - - SHA1Final(this, allocated_hash.ptr); - this->public.hasher_interface.reset(&(this->public.hasher_interface)); - - *hash = allocated_hash; - } -} - -/** - * Implementation of hasher_t.get_hash_size. - */ -static size_t get_hash_size(private_sha1_hasher_t *this) -{ - return HASH_SIZE_SHA1; -} - -/** - * Implementation of hasher_t.reset. - */ -static void reset(private_sha1_hasher_t *this) -{ - this->state[0] = 0x67452301; - this->state[1] = 0xEFCDAB89; - this->state[2] = 0x98BADCFE; - this->state[3] = 0x10325476; - this->state[4] = 0xC3D2E1F0; - this->count[0] = 0; - this->count[1] = 0; -} - -/** - * Implementation of hasher_t.get_state - */ -static chunk_t get_state(private_sha1_hasher_t *this) -{ - chunk_t chunk; - - chunk.ptr = (u_char*)&this->state[0]; - chunk.len = sizeof(this->state); - - return chunk; -} - -/** - * Implementation of hasher_t.destroy. - */ -static void destroy(private_sha1_hasher_t *this) -{ - free(this); -} - -/* - * Described in header. - */ -sha1_hasher_t *sha1_hasher_create(void) -{ - private_sha1_hasher_t *this = malloc_thing(private_sha1_hasher_t); - - this->public.hasher_interface.get_hash = (void (*) (hasher_t*, chunk_t, u_int8_t*))get_hash; - this->public.hasher_interface.allocate_hash = (void (*) (hasher_t*, chunk_t, chunk_t*))allocate_hash; - this->public.hasher_interface.get_hash_size = (size_t (*) (hasher_t*))get_hash_size; - this->public.hasher_interface.reset = (void (*) (hasher_t*))reset; - this->public.hasher_interface.get_state = (chunk_t (*) (hasher_t*))get_state; - this->public.hasher_interface.destroy = (void (*) (hasher_t*))destroy; - - /* initialize */ - reset(this); - - return &(this->public); -} diff --git a/src/libstrongswan/crypto/hashers/sha1_hasher.h b/src/libstrongswan/crypto/hashers/sha1_hasher.h deleted file mode 100644 index 380fa9845..000000000 --- a/src/libstrongswan/crypto/hashers/sha1_hasher.h +++ /dev/null @@ -1,60 +0,0 @@ -/** - * @file sha1_hasher.h - * - * @brief Interface of sha1_hasher_t - * - */ - -/* - * Copyright (C) 2005-2006 Martin Willi - * Copyright (C) 2005 Jan Hutter - * Hochschule fuer Technik Rapperswil - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -#ifndef SHA1_HASHER_H_ -#define SHA1_HASHER_H_ - -typedef struct sha1_hasher_t sha1_hasher_t; - -#include <crypto/hashers/hasher.h> - -/** - * @brief Implementation of hasher_t interface using the - * SHA1 algorithm. - * - * @b Constructors: - * - hasher_create() using HASH_SHA1 as algorithm - * - sha1_hasher_create() - * - * @see hasher_t - * - * @ingroup hashers - */ -struct sha1_hasher_t { - - /** - * Generic hasher_t interface for this hasher. - */ - hasher_t hasher_interface; -}; - -/** - * @brief Creates a new sha1_hasher_t. - * - * @return sha1_hasher_t object - * - * @ingroup hashers - */ -sha1_hasher_t *sha1_hasher_create(void); - -#endif /*SHA1_HASHER_H_*/ diff --git a/src/libstrongswan/crypto/hashers/sha2_hasher.c b/src/libstrongswan/crypto/hashers/sha2_hasher.c deleted file mode 100644 index b68972cec..000000000 --- a/src/libstrongswan/crypto/hashers/sha2_hasher.c +++ /dev/null @@ -1,672 +0,0 @@ -/** - * @file sha2_hasher.c - * - * @brief Implementation of hasher_sha_t. - * - */ - -/* - * Copyright (C) 2006 Martin Willi - * Hochschule fuer Technik Rapperswil - * Copyright (C) 2001 Jari Ruusu. - * - * Ported from strongSwans implementation written by Jari Ruusu. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -#include <string.h> - -#include "sha2_hasher.h" - - -typedef struct private_sha512_hasher_t private_sha512_hasher_t; - -/** - * Private data structure with hasing context for SHA384 and SHA512 - */ -struct private_sha512_hasher_t { - /** - * Public interface for this hasher. - */ - sha2_hasher_t public; - - unsigned char sha_out[128]; /* results are here, bytes 0..47/0..63 */ - u_int64_t sha_H[8]; - u_int64_t sha_blocks; - u_int64_t sha_blocksMSB; - int sha_bufCnt; -}; - - -typedef struct private_sha256_hasher_t private_sha256_hasher_t; - -/** - * Private data structure with hasing context for SHA256 - */ -struct private_sha256_hasher_t { - /** - * Public interface for this hasher. - */ - sha2_hasher_t public; - - unsigned char sha_out[64]; /* results are here, bytes 0...31 */ - u_int32_t sha_H[8]; - u_int64_t sha_blocks; - int sha_bufCnt; -}; - - -static const u_int32_t sha256_hashInit[8] = { - 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, - 0x1f83d9ab, 0x5be0cd19 -}; - -static const u_int32_t sha256_K[64] = { - 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, - 0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, - 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 0xe49b69c1, 0xefbe4786, - 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, - 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, - 0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, - 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 0xa2bfe8a1, 0xa81a664b, - 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, - 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, - 0x5b9cca4f, 0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, - 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 -}; - -static const u_int64_t sha512_hashInit[8] = { - 0x6a09e667f3bcc908ULL, 0xbb67ae8584caa73bULL, 0x3c6ef372fe94f82bULL, - 0xa54ff53a5f1d36f1ULL, 0x510e527fade682d1ULL, 0x9b05688c2b3e6c1fULL, - 0x1f83d9abfb41bd6bULL, 0x5be0cd19137e2179ULL -}; - -static const u_int64_t sha384_hashInit[8] = { - 0xcbbb9d5dc1059ed8ULL, 0x629a292a367cd507ULL, 0x9159015a3070dd17ULL, - 0x152fecd8f70e5939ULL, 0x67332667ffc00b31ULL, 0x8eb44a8768581511ULL, - 0xdb0c2e0d64f98fa7ULL, 0x47b5481dbefa4fa4ULL -}; - -static const u_int64_t sha512_K[80] = { - 0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL, 0xb5c0fbcfec4d3b2fULL, - 0xe9b5dba58189dbbcULL, 0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL, - 0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL, 0xd807aa98a3030242ULL, - 0x12835b0145706fbeULL, 0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL, - 0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL, 0x9bdc06a725c71235ULL, - 0xc19bf174cf692694ULL, 0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL, - 0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL, 0x2de92c6f592b0275ULL, - 0x4a7484aa6ea6e483ULL, 0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL, - 0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL, 0xb00327c898fb213fULL, - 0xbf597fc7beef0ee4ULL, 0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL, - 0x06ca6351e003826fULL, 0x142929670a0e6e70ULL, 0x27b70a8546d22ffcULL, - 0x2e1b21385c26c926ULL, 0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL, - 0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL, 0x81c2c92e47edaee6ULL, - 0x92722c851482353bULL, 0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL, - 0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL, 0xd192e819d6ef5218ULL, - 0xd69906245565a910ULL, 0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL, - 0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL, 0x2748774cdf8eeb99ULL, - 0x34b0bcb5e19b48a8ULL, 0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL, - 0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL, 0x748f82ee5defb2fcULL, - 0x78a5636f43172f60ULL, 0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL, - 0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL, 0xbef9a3f7b2c67915ULL, - 0xc67178f2e372532bULL, 0xca273eceea26619cULL, 0xd186b8c721c0c207ULL, - 0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL, 0x06f067aa72176fbaULL, - 0x0a637dc5a2c898a6ULL, 0x113f9804bef90daeULL, 0x1b710b35131c471bULL, - 0x28db77f523047d84ULL, 0x32caab7b40c72493ULL, 0x3c9ebe0a15c9bebcULL, - 0x431d67c49c100d4cULL, 0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL, - 0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL -}; - - -/* set macros for SHA256 */ -#define Ch(x,y,z) (((x) & (y)) ^ ((~(x)) & (z))) -#define Maj(x,y,z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z))) -#define R(x,y) ((y) >> (x)) - -#define S(x,y) (((y) >> (x)) | ((y) << (32 - (x)))) -#define uSig0(x) ((S(2,(x))) ^ (S(13,(x))) ^ (S(22,(x)))) -#define uSig1(x) ((S(6,(x))) ^ (S(11,(x))) ^ (S(25,(x)))) -#define lSig0(x) ((S(7,(x))) ^ (S(18,(x))) ^ (R(3,(x)))) -#define lSig1(x) ((S(17,(x))) ^ (S(19,(x))) ^ (R(10,(x)))) - -/** - * Single block SHA256 transformation - */ -static void sha256_transform(private_sha256_hasher_t *ctx, - const unsigned char *datap) -{ - register int j; - u_int32_t a, b, c, d, e, f, g, h; - u_int32_t T1, T2, W[64], Wm2, Wm15; - - /* read the data, big endian byte order */ - j = 0; - do { - W[j] = (((u_int32_t)(datap[0]))<<24) | (((u_int32_t)(datap[1]))<<16) | - (((u_int32_t)(datap[2]))<<8 ) | ((u_int32_t)(datap[3])); - datap += 4; - } while(++j < 16); - - /* initialize variables a...h */ - a = ctx->sha_H[0]; - b = ctx->sha_H[1]; - c = ctx->sha_H[2]; - d = ctx->sha_H[3]; - e = ctx->sha_H[4]; - f = ctx->sha_H[5]; - g = ctx->sha_H[6]; - h = ctx->sha_H[7]; - - /* apply compression function */ - j = 0; - do - { - if(j >= 16) - { - Wm2 = W[j - 2]; - Wm15 = W[j - 15]; - W[j] = lSig1(Wm2) + W[j - 7] + lSig0(Wm15) + W[j - 16]; - } - T1 = h + uSig1(e) + Ch(e,f,g) + sha256_K[j] + W[j]; - T2 = uSig0(a) + Maj(a,b,c); - h = g; g = f; f = e; - e = d + T1; - d = c; c = b; b = a; - a = T1 + T2; - } while(++j < 64); - - /* compute intermediate hash value */ - ctx->sha_H[0] += a; - ctx->sha_H[1] += b; - ctx->sha_H[2] += c; - ctx->sha_H[3] += d; - ctx->sha_H[4] += e; - ctx->sha_H[5] += f; - ctx->sha_H[6] += g; - ctx->sha_H[7] += h; - - ctx->sha_blocks++; -} - -/** - * Update SHA256 hash - */ -static void sha256_write(private_sha256_hasher_t *ctx, - const unsigned char *datap, int length) -{ - while(length > 0) - { - if(!ctx->sha_bufCnt) - { - while(length >= sizeof(ctx->sha_out)) - { - sha256_transform(ctx, datap); - datap += sizeof(ctx->sha_out); - length -= sizeof(ctx->sha_out); - } - if(!length) return; - } - ctx->sha_out[ctx->sha_bufCnt] = *datap++; - length--; - if(++ctx->sha_bufCnt == sizeof(ctx->sha_out)) - { - sha256_transform(ctx, &ctx->sha_out[0]); - ctx->sha_bufCnt = 0; - } - } -} - -/** - * finalize SHA256 hash - */ -static void sha256_final(private_sha256_hasher_t *ctx) -{ - register int j; - u_int64_t bitLength; - u_int32_t i; - unsigned char padByte, *datap; - - bitLength = (ctx->sha_blocks << 9) | (ctx->sha_bufCnt << 3); - padByte = 0x80; - sha256_write(ctx, &padByte, 1); - - /* pad extra space with zeroes */ - padByte = 0; - while(ctx->sha_bufCnt != 56) - { - sha256_write(ctx, &padByte, 1); - } - - /* write bit length, big endian byte order */ - ctx->sha_out[56] = bitLength >> 56; - ctx->sha_out[57] = bitLength >> 48; - ctx->sha_out[58] = bitLength >> 40; - ctx->sha_out[59] = bitLength >> 32; - ctx->sha_out[60] = bitLength >> 24; - ctx->sha_out[61] = bitLength >> 16; - ctx->sha_out[62] = bitLength >> 8; - ctx->sha_out[63] = bitLength; - sha256_transform(ctx, &ctx->sha_out[0]); - - /* return results in ctx->sha_out[0...31] */ - datap = &ctx->sha_out[0]; - j = 0; - do { - i = ctx->sha_H[j]; - datap[0] = i >> 24; - datap[1] = i >> 16; - datap[2] = i >> 8; - datap[3] = i; - datap += 4; - } while(++j < 8); -} - -/* update macros for SHA512 */ -#undef S -#undef uSig0 -#undef uSig1 -#undef lSig0 -#undef lSig1 -#define S(x,y) (((y) >> (x)) | ((y) << (64 - (x)))) -#define uSig0(x) ((S(28,(x))) ^ (S(34,(x))) ^ (S(39,(x)))) -#define uSig1(x) ((S(14,(x))) ^ (S(18,(x))) ^ (S(41,(x)))) -#define lSig0(x) ((S(1,(x))) ^ (S(8,(x))) ^ (R(7,(x)))) -#define lSig1(x) ((S(19,(x))) ^ (S(61,(x))) ^ (R(6,(x)))) - -/** - * Single block SHA384/SHA512 transformation - */ -static void sha512_transform(private_sha512_hasher_t *ctx, - const unsigned char *datap) -{ - register int j; - u_int64_t a, b, c, d, e, f, g, h; - u_int64_t T1, T2, W[80], Wm2, Wm15; - - /* read the data, big endian byte order */ - j = 0; - do { - W[j] = (((u_int64_t)(datap[0]))<<56) | (((u_int64_t)(datap[1]))<<48) | - (((u_int64_t)(datap[2]))<<40) | (((u_int64_t)(datap[3]))<<32) | - (((u_int64_t)(datap[4]))<<24) | (((u_int64_t)(datap[5]))<<16) | - (((u_int64_t)(datap[6]))<<8 ) | ((u_int64_t)(datap[7])); - datap += 8; - } while(++j < 16); - - /* initialize variables a...h */ - a = ctx->sha_H[0]; - b = ctx->sha_H[1]; - c = ctx->sha_H[2]; - d = ctx->sha_H[3]; - e = ctx->sha_H[4]; - f = ctx->sha_H[5]; - g = ctx->sha_H[6]; - h = ctx->sha_H[7]; - - /* apply compression function */ - j = 0; - do { - if(j >= 16) { - Wm2 = W[j - 2]; - Wm15 = W[j - 15]; - W[j] = lSig1(Wm2) + W[j - 7] + lSig0(Wm15) + W[j - 16]; - } - T1 = h + uSig1(e) + Ch(e,f,g) + sha512_K[j] + W[j]; - T2 = uSig0(a) + Maj(a,b,c); - h = g; g = f; f = e; - e = d + T1; - d = c; c = b; b = a; - a = T1 + T2; - } while(++j < 80); - - /* compute intermediate hash value */ - ctx->sha_H[0] += a; - ctx->sha_H[1] += b; - ctx->sha_H[2] += c; - ctx->sha_H[3] += d; - ctx->sha_H[4] += e; - ctx->sha_H[5] += f; - ctx->sha_H[6] += g; - ctx->sha_H[7] += h; - - ctx->sha_blocks++; - if(!ctx->sha_blocks) ctx->sha_blocksMSB++; -} - -/** - * Update a SHA384/SHA512 hash - */ -static void sha512_write(private_sha512_hasher_t *ctx, - const unsigned char *datap, int length) -{ - while(length > 0) - { - if(!ctx->sha_bufCnt) - { - while(length >= sizeof(ctx->sha_out)) - { - sha512_transform(ctx, datap); - datap += sizeof(ctx->sha_out); - length -= sizeof(ctx->sha_out); - } - if(!length) return; - } - ctx->sha_out[ctx->sha_bufCnt] = *datap++; - length--; - if(++ctx->sha_bufCnt == sizeof(ctx->sha_out)) - { - sha512_transform(ctx, &ctx->sha_out[0]); - ctx->sha_bufCnt = 0; - } - } -} - -/** - * Finalize a SHA384/SHA512 hash - */ -static void sha512_final(private_sha512_hasher_t *ctx) -{ - register int j; - u_int64_t bitLength, bitLengthMSB; - u_int64_t i; - unsigned char padByte, *datap; - - bitLength = (ctx->sha_blocks << 10) | (ctx->sha_bufCnt << 3); - bitLengthMSB = (ctx->sha_blocksMSB << 10) | (ctx->sha_blocks >> 54); - padByte = 0x80; - sha512_write(ctx, &padByte, 1); - - /* pad extra space with zeroes */ - padByte = 0; - while(ctx->sha_bufCnt != 112) - { - sha512_write(ctx, &padByte, 1); - } - - /* write bit length, big endian byte order */ - ctx->sha_out[112] = bitLengthMSB >> 56; - ctx->sha_out[113] = bitLengthMSB >> 48; - ctx->sha_out[114] = bitLengthMSB >> 40; - ctx->sha_out[115] = bitLengthMSB >> 32; - ctx->sha_out[116] = bitLengthMSB >> 24; - ctx->sha_out[117] = bitLengthMSB >> 16; - ctx->sha_out[118] = bitLengthMSB >> 8; - ctx->sha_out[119] = bitLengthMSB; - ctx->sha_out[120] = bitLength >> 56; - ctx->sha_out[121] = bitLength >> 48; - ctx->sha_out[122] = bitLength >> 40; - ctx->sha_out[123] = bitLength >> 32; - ctx->sha_out[124] = bitLength >> 24; - ctx->sha_out[125] = bitLength >> 16; - ctx->sha_out[126] = bitLength >> 8; - ctx->sha_out[127] = bitLength; - sha512_transform(ctx, &ctx->sha_out[0]); - - /* return results in ctx->sha_out[0...63] */ - datap = &ctx->sha_out[0]; - j = 0; - do { - i = ctx->sha_H[j]; - datap[0] = i >> 56; - datap[1] = i >> 48; - datap[2] = i >> 40; - datap[3] = i >> 32; - datap[4] = i >> 24; - datap[5] = i >> 16; - datap[6] = i >> 8; - datap[7] = i; - datap += 8; - } while(++j < 8); -} - -/** - * Implementation of hasher_t.get_hash for SHA256. - */ -static void get_hash256(private_sha256_hasher_t *this, - chunk_t chunk, u_int8_t *buffer) -{ - sha256_write(this, chunk.ptr, chunk.len); - if (buffer != NULL) - { - sha256_final(this); - memcpy(buffer, this->sha_out, HASH_SIZE_SHA256); - this->public.hasher_interface.reset(&(this->public.hasher_interface)); - } -} - -/** - * Implementation of hasher_t.get_hash for SHA384. - */ -static void get_hash384(private_sha512_hasher_t *this, - chunk_t chunk, u_int8_t *buffer) -{ - sha512_write(this, chunk.ptr, chunk.len); - if (buffer != NULL) - { - sha512_final(this); - memcpy(buffer, this->sha_out, HASH_SIZE_SHA384); - this->public.hasher_interface.reset(&(this->public.hasher_interface)); - } -} - -/** - * Implementation of hasher_t.get_hash for SHA512. - */ -static void get_hash512(private_sha512_hasher_t *this, - chunk_t chunk, u_int8_t *buffer) -{ - sha512_write(this, chunk.ptr, chunk.len); - if (buffer != NULL) - { - sha512_final(this); - memcpy(buffer, this->sha_out, HASH_SIZE_SHA512); - this->public.hasher_interface.reset(&(this->public.hasher_interface)); - } -} - -/** - * Implementation of hasher_t.allocate_hash for SHA256. - */ -static void allocate_hash256(private_sha256_hasher_t *this, - chunk_t chunk, chunk_t *hash) -{ - chunk_t allocated_hash; - - sha256_write(this, chunk.ptr, chunk.len); - if (hash != NULL) - { - sha256_final(this); - allocated_hash = chunk_alloc(HASH_SIZE_SHA256); - memcpy(allocated_hash.ptr, this->sha_out, HASH_SIZE_SHA256); - this->public.hasher_interface.reset(&(this->public.hasher_interface)); - *hash = allocated_hash; - } -} - -/** - * Implementation of hasher_t.allocate_hash for SHA384. - */ -static void allocate_hash384(private_sha512_hasher_t *this, - chunk_t chunk, chunk_t *hash) -{ - chunk_t allocated_hash; - - sha512_write(this, chunk.ptr, chunk.len); - if (hash != NULL) - { - sha512_final(this); - allocated_hash = chunk_alloc(HASH_SIZE_SHA384); - memcpy(allocated_hash.ptr, this->sha_out, HASH_SIZE_SHA384); - this->public.hasher_interface.reset(&(this->public.hasher_interface)); - *hash = allocated_hash; - } -} - -/** - * Implementation of hasher_t.allocate_hash for SHA512. - */ -static void allocate_hash512(private_sha512_hasher_t *this, - chunk_t chunk, chunk_t *hash) -{ - chunk_t allocated_hash; - - sha512_write(this, chunk.ptr, chunk.len); - if (hash != NULL) - { - sha512_final(this); - allocated_hash = chunk_alloc(HASH_SIZE_SHA512); - memcpy(allocated_hash.ptr, this->sha_out, HASH_SIZE_SHA512); - this->public.hasher_interface.reset(&(this->public.hasher_interface)); - *hash = allocated_hash; - } -} - -/** - * Implementation of hasher_t.get_hash_size for SHA256. - */ -static size_t get_hash_size256(private_sha256_hasher_t *this) -{ - return HASH_SIZE_SHA256; -} - -/** - * Implementation of hasher_t.get_hash_size for SHA384. - */ -static size_t get_hash_size384(private_sha512_hasher_t *this) -{ - return HASH_SIZE_SHA384; -} - -/** - * Implementation of hasher_t.get_hash_size for SHA512. - */ -static size_t get_hash_size512(private_sha512_hasher_t *this) -{ - return HASH_SIZE_SHA512; -} - -/** - * Implementation of hasher_t.reset for SHA256 - */ -static void reset256(private_sha256_hasher_t *ctx) -{ - memcpy(&ctx->sha_H[0], &sha256_hashInit[0], sizeof(ctx->sha_H)); - ctx->sha_blocks = 0; - ctx->sha_bufCnt = 0; -} - -/** - * Implementation of hasher_t.reset for SHA384 - */ -static void reset384(private_sha512_hasher_t *ctx) -{ - memcpy(&ctx->sha_H[0], &sha384_hashInit[0], sizeof(ctx->sha_H)); - ctx->sha_blocks = 0; - ctx->sha_blocksMSB = 0; - ctx->sha_bufCnt = 0; -} - -/** - * Implementation of hasher_t.reset for SHA512 - */ -static void reset512(private_sha512_hasher_t *ctx) -{ - memcpy(&ctx->sha_H[0], &sha512_hashInit[0], sizeof(ctx->sha_H)); - ctx->sha_blocks = 0; - ctx->sha_blocksMSB = 0; - ctx->sha_bufCnt = 0; -} - -/** - * Implementation of hasher_t.get_state for SHA256 - */ -static chunk_t get_state256(private_sha256_hasher_t *ctx) -{ - chunk_t chunk; - chunk.ptr = (u_char*)&ctx->sha_H[0]; - chunk.len = HASH_SIZE_SHA256; - return chunk; -} - -/** - * Implementation of hasher_t.get_state for SHA384 - */ -static chunk_t get_state384(private_sha512_hasher_t *ctx) -{ - chunk_t chunk; - chunk.ptr = (u_char*)&ctx->sha_H[0]; - chunk.len = HASH_SIZE_SHA384; - return chunk; -} -/** - * Implementation of hasher_t.get_state for SHA512 - */ -static chunk_t get_state512(private_sha512_hasher_t *ctx) -{ - chunk_t chunk; - chunk.ptr = (u_char*)&ctx->sha_H[0]; - chunk.len = HASH_SIZE_SHA512; - return chunk; -} - -/** - * Implementation of hasher_t.destroy. - */ -static void destroy(sha2_hasher_t *this) -{ - free(this); -} - -/* - * Described in header. - */ -sha2_hasher_t *sha2_hasher_create(hash_algorithm_t algorithm) -{ - sha2_hasher_t *this; - - switch (algorithm) - { - case HASH_SHA256: - this = (sha2_hasher_t*)malloc_thing(private_sha256_hasher_t); - this->hasher_interface.reset = (void(*)(hasher_t*))reset256; - this->hasher_interface.get_state = (chunk_t(*)(hasher_t*))get_state256; - this->hasher_interface.get_hash_size = (size_t(*)(hasher_t*))get_hash_size256; - this->hasher_interface.get_hash = (void(*)(hasher_t*,chunk_t,u_int8_t*))get_hash256; - this->hasher_interface.allocate_hash = (void(*)(hasher_t*,chunk_t,chunk_t*))allocate_hash256; - break; - case HASH_SHA384: - /* uses SHA512 data structure */ - this = (sha2_hasher_t*)malloc_thing(private_sha512_hasher_t); - this->hasher_interface.reset = (void(*)(hasher_t*))reset384; - this->hasher_interface.get_state = (chunk_t(*)(hasher_t*))get_state384; - this->hasher_interface.get_hash_size = (size_t(*)(hasher_t*))get_hash_size384; - this->hasher_interface.get_hash = (void(*)(hasher_t*,chunk_t,u_int8_t*))get_hash384; - this->hasher_interface.allocate_hash = (void(*)(hasher_t*,chunk_t,chunk_t*))allocate_hash384; - break; - case HASH_SHA512: - this = (sha2_hasher_t*)malloc_thing(private_sha512_hasher_t); - this->hasher_interface.reset = (void(*)(hasher_t*))reset512; - this->hasher_interface.get_state = (chunk_t(*)(hasher_t*))get_state512; - this->hasher_interface.get_hash_size = (size_t(*)(hasher_t*))get_hash_size512; - this->hasher_interface.get_hash = (void(*)(hasher_t*,chunk_t,u_int8_t*))get_hash512; - this->hasher_interface.allocate_hash = (void(*)(hasher_t*,chunk_t,chunk_t*))allocate_hash512; - break; - default: - return NULL; - } - this->hasher_interface.destroy = (void(*)(hasher_t*))destroy; - - /* initialize */ - this->hasher_interface.reset(&this->hasher_interface); - - return this; -} diff --git a/src/libstrongswan/crypto/hashers/sha2_hasher.h b/src/libstrongswan/crypto/hashers/sha2_hasher.h deleted file mode 100644 index 91e82fedb..000000000 --- a/src/libstrongswan/crypto/hashers/sha2_hasher.h +++ /dev/null @@ -1,62 +0,0 @@ -/** - * @file sha2_hasher.h - * - * @brief Interface of sha2_hasher_t - * - */ - -/* - * Copyright (C) 2006 Martin Willi - * Hochschule fuer Technik Rapperswil - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -#ifndef SHA2_HASHER_H_ -#define SHA2_HASHER_H_ - -typedef struct sha2_hasher_t sha2_hasher_t; - -#include <crypto/hashers/hasher.h> - -/** - * @brief Implementation of hasher_t interface using the SHA2 algorithms. - * - * SHA2 is an other name for the SHA-256, SHA-384 and SHA-512 variants of - * the SHA hash algorithm. - * - * @b Constructors: - * - hasher_create() using HASH_SHA256, HASH_SHA384 or HASH_SHA512 as algorithm - * - sha2_hasher_create() - * - * @see hasher_t - * - * @ingroup hashers - */ -struct sha2_hasher_t { - - /** - * Generic hasher_t interface for this hasher. - */ - hasher_t hasher_interface; -}; - -/** - * @brief Creates a new sha2_hasher_t. - * - * @param algorithm HASH_SHA256, HASH_SHA384 or HASH_SHA512 - * @return sha2_hasher_t object - * - * @ingroup hashers - */ -sha2_hasher_t *sha2_hasher_create(hash_algorithm_t algorithm); - -#endif /* SHA2_HASHER_H_ */ diff --git a/src/libstrongswan/crypto/hmac.c b/src/libstrongswan/crypto/hmac.c deleted file mode 100644 index df4f90bc8..000000000 --- a/src/libstrongswan/crypto/hmac.c +++ /dev/null @@ -1,215 +0,0 @@ -/** - * @file hmac.c - * - * @brief Implementation of hmac_t. - */ - -/* - * Copyright (C) 2005-2006 Martin Willi - * Copyright (C) 2005 Jan Hutter - * Hochschule fuer Technik Rapperswil - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General hmac License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General hmac License - * for more details. - */ - -#include <string.h> - -#include "hmac.h" - - -typedef struct private_hmac_t private_hmac_t; - -/** - * Private data of a hmac_t object. - * - * The variable names are the same as in the RFC. - */ -struct private_hmac_t { - /** - * Public hmac_t interface. - */ - hmac_t hmac; - - /** - * Block size, as in RFC. - */ - u_int8_t b; - - /** - * Hash function. - */ - hasher_t *h; - - /** - * Previously xor'ed key using opad. - */ - chunk_t opaded_key; - - /** - * Previously xor'ed key using ipad. - */ - chunk_t ipaded_key; -}; - -/** - * Implementation of hmac_t.get_mac. - */ -static void get_mac(private_hmac_t *this, chunk_t data, u_int8_t *out) -{ - /* H(K XOR opad, H(K XOR ipad, text)) - * - * if out is NULL, we append text to the inner hash. - * else, we complete the inner and do the outer. - * - */ - - u_int8_t buffer[this->h->get_hash_size(this->h)]; - chunk_t inner; - - if (out == NULL) - { - /* append data to inner */ - this->h->get_hash(this->h, data, NULL); - } - else - { - /* append and do outer hash */ - inner.ptr = buffer; - inner.len = this->h->get_hash_size(this->h); - - /* complete inner */ - this->h->get_hash(this->h, data, buffer); - - /* do outer */ - this->h->get_hash(this->h, this->opaded_key, NULL); - this->h->get_hash(this->h, inner, out); - - /* reinit for next call */ - this->h->get_hash(this->h, this->ipaded_key, NULL); - } -} - -/** - * Implementation of hmac_t.allocate_mac. - */ -static void allocate_mac(private_hmac_t *this, chunk_t data, chunk_t *out) -{ - /* allocate space and use get_mac */ - if (out == NULL) - { - /* append mode */ - this->hmac.get_mac(&(this->hmac), data, NULL); - } - else - { - out->len = this->h->get_hash_size(this->h); - out->ptr = malloc(out->len); - this->hmac.get_mac(&(this->hmac), data, out->ptr); - } -} - -/** - * Implementation of hmac_t.get_block_size. - */ -static size_t get_block_size(private_hmac_t *this) -{ - return this->h->get_hash_size(this->h); -} - -/** - * Implementation of hmac_t.set_key. - */ -static void set_key(private_hmac_t *this, chunk_t key) -{ - int i; - u_int8_t buffer[this->b]; - - memset(buffer, 0, this->b); - - if (key.len > this->b) - { - /* if key is too long, it will be hashed */ - this->h->get_hash(this->h, key, buffer); - } - else - { - /* if not, just copy it in our pre-padded k */ - memcpy(buffer, key.ptr, key.len); - } - - /* apply ipad and opad to key */ - for (i = 0; i < this->b; i++) - { - this->ipaded_key.ptr[i] = buffer[i] ^ 0x36; - this->opaded_key.ptr[i] = buffer[i] ^ 0x5C; - } - - /* begin hashing of inner pad */ - this->h->reset(this->h); - this->h->get_hash(this->h, this->ipaded_key, NULL); -} - -/** - * Implementation of hmac_t.destroy. - */ -static void destroy(private_hmac_t *this) -{ - this->h->destroy(this->h); - free(this->opaded_key.ptr); - free(this->ipaded_key.ptr); - free(this); -} - -/* - * Described in header - */ -hmac_t *hmac_create(hash_algorithm_t hash_algorithm) -{ - private_hmac_t *this; - - this = malloc_thing(private_hmac_t); - - /* set hmac_t methods */ - this->hmac.get_mac = (void (*)(hmac_t *,chunk_t,u_int8_t*))get_mac; - this->hmac.allocate_mac = (void (*)(hmac_t *,chunk_t,chunk_t*))allocate_mac; - this->hmac.get_block_size = (size_t (*)(hmac_t *))get_block_size; - this->hmac.set_key = (void (*)(hmac_t *,chunk_t))set_key; - this->hmac.destroy = (void (*)(hmac_t *))destroy; - - /* set b, according to hasher */ - switch (hash_algorithm) - { - case HASH_SHA1: - case HASH_MD5: - case HASH_SHA256: - this->b = 64; - break; - case HASH_SHA384: - case HASH_SHA512: - this->b = 128; - break; - default: - free(this); - return NULL; - } - - /* build the hasher */ - this->h = hasher_create(hash_algorithm); - - /* build ipad and opad */ - this->opaded_key.ptr = malloc(this->b); - this->opaded_key.len = this->b; - - this->ipaded_key.ptr = malloc(this->b); - this->ipaded_key.len = this->b; - - return &(this->hmac); -} diff --git a/src/libstrongswan/crypto/hmac.h b/src/libstrongswan/crypto/hmac.h deleted file mode 100644 index 06b75aaf9..000000000 --- a/src/libstrongswan/crypto/hmac.h +++ /dev/null @@ -1,117 +0,0 @@ -/** - * @file hmac.h - * - * @brief Interface of hmac_t. - */ - -/* - * Copyright (C) 2005-2006 Martin Willi - * Copyright (C) 2005 Jan Hutter - * Hochschule fuer Technik Rapperswil - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -#ifndef HMAC_H_ -#define HMAC_H_ - -typedef struct hmac_t hmac_t; - -#include <crypto/hashers/hasher.h> - -/** - * @brief Message authentication using hash functions. - * - * This class implements the message authenticaion algorithm - * described in RFC2104. It uses a hash function, wich must - * be implemented as a hasher_t class. - * - * See http://www.faqs.org/rfcs/rfc2104.html for RFC. - * @see - * - hasher_t - * - prf_hmac_t - * - * @b Constructors: - * - hmac_create() - * - * @ingroup crypto - */ -struct hmac_t { - /** - * @brief Generate message authentication code. - * - * If buffer is NULL, no result is given back. A next call will - * append the data to already supplied data. If buffer is not NULL, - * the mac of all apended data is calculated, returned and the - * state of the hmac_t is reseted. - * - * @param this calling object - * @param data chunk of data to authenticate - * @param[out] buffer pointer where the generated bytes will be written - */ - void (*get_mac) (hmac_t *this, chunk_t data, u_int8_t *buffer); - - /** - * @brief Generates message authentication code and - * allocate space for them. - * - * If chunk is NULL, no result is given back. A next call will - * append the data to already supplied. If chunk is not NULL, - * the mac of all apended data is calculated, returned and the - * state of the hmac_t reset; - * - * @param this calling object - * @param data chunk of data to authenticate - * @param[out] chunk chunk which will hold generated bytes - */ - void (*allocate_mac) (hmac_t *this, chunk_t data, chunk_t *chunk); - - /** - * @brief Get the block size of this hmac_t object. - * - * @param this calling object - * @return block size in bytes - */ - size_t (*get_block_size) (hmac_t *this); - - /** - * @brief Set the key for this hmac_t object. - * - * Any key length is accepted. - * - * @param this calling object - * @param key key to set - */ - void (*set_key) (hmac_t *this, chunk_t key); - - /** - * @brief Destroys a hmac_t object. - * - * @param this calling object - */ - void (*destroy) (hmac_t *this); -}; - -/** - * @brief Creates a new hmac_t object. - * - * Creates a hasher_t object internally. - * - * @param hash_algorithm hash algorithm to use - * @return - * - hmac_t object - * - NULL if hash algorithm is not supported - * - * @ingroup transforms - */ -hmac_t *hmac_create(hash_algorithm_t hash_algorithm); - -#endif /*HMAC_H_*/ diff --git a/src/libstrongswan/crypto/ietf_attr_list.c b/src/libstrongswan/crypto/ietf_attr_list.c deleted file mode 100644 index 1ecadf679..000000000 --- a/src/libstrongswan/crypto/ietf_attr_list.c +++ /dev/null @@ -1,405 +0,0 @@ -/** - * @file ietf_attr.c - * - * @brief Implementation of ietfAttr_t. - * - */ - -/* - * Copyright (C) 2007 Andreas Steffen, Hochschule fuer Technik Rapperswil - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -#include <string.h> -#include <stdio.h> - -#include <debug.h> -#include <asn1/asn1.h> -#include <utils/lexparser.h> - -#include "ietf_attr_list.h" - -/** - * Private definition of ietfAttribute kinds - */ -typedef enum { - IETF_ATTRIBUTE_OCTETS = 0, - IETF_ATTRIBUTE_OID = 1, - IETF_ATTRIBUTE_STRING = 2 -} ietfAttribute_t; - -typedef struct ietfAttr_t ietfAttr_t; - -/** - * Private definition of an ietfAttribute - */ -struct ietfAttr_t { - /** - * IETF attribute kind - */ - ietfAttribute_t kind; - - /** - * IETF attribute valuse - */ - chunk_t value; - - /** - * Compares two ietfAttributes - * - * return -1 if this is earlier in the alphabet than other - * return 0 if this equals other - * return +1 if this is later in the alphabet than other - * - * @param this calling object - * @param other other object - */ - int (*compare) (const ietfAttr_t *this ,const ietfAttr_t *other); - - /** - * Destroys the ietfAttr_t object. - * - * @param this ietfAttr_t to destroy - */ - void (*destroy) (ietfAttr_t *this); -}; - -/** - * Implements ietfAttr_t.compare. - */ -static int ietfAttr_compare(const ietfAttr_t *this ,const ietfAttr_t *other) -{ - int cmp_len, len, cmp_value; - - /* OID attributes are appended after STRING and OCTETS attributes */ - if (this->kind != IETF_ATTRIBUTE_OID && other->kind == IETF_ATTRIBUTE_OID) - { - return -1; - } - if (this->kind == IETF_ATTRIBUTE_OID && other->kind != IETF_ATTRIBUTE_OID) - { - return 1; - } - - cmp_len = this->value.len - other->value.len; - len = (cmp_len < 0)? this->value.len : other->value.len; - cmp_value = memcmp(this->value.ptr, other->value.ptr, len); - - return (cmp_value == 0)? cmp_len : cmp_value; -} - -/** - * Implements ietfAttr_t.destroy. - */ -static void ietfAttr_destroy(ietfAttr_t *this) -{ - free(this->value.ptr); - free(this); -} - -/** - * Creates an ietfAttr_t object. - */ -static ietfAttr_t *ietfAttr_create(ietfAttribute_t kind, chunk_t value) -{ - ietfAttr_t *this = malloc_thing(ietfAttr_t); - - /* initialize */ - this->kind = kind; - this->value = chunk_clone(value); - - /* function */ - this->compare = ietfAttr_compare; - this->destroy = ietfAttr_destroy; - - return this; -} - -/** - * Adds an ietfAttr_t object to a sorted linked list - */ -static void ietfAttr_add(linked_list_t *list, ietfAttr_t *attr) -{ - iterator_t *iterator = list->create_iterator(list, TRUE); - ietfAttr_t *current_attr; - bool found = FALSE; - - while (iterator->iterate(iterator, (void **)¤t_attr)) - { - int cmp = attr->compare(attr, current_attr); - - if (cmp > 0) - { - continue; - } - if (cmp == 0) - { - attr->destroy(attr); - } - else - { - iterator->insert_before(iterator, attr); - } - found = TRUE; - break; - } - iterator->destroy(iterator); - if (!found) - { - list->insert_last(list, attr); - } -} - -/* - * Described in header. - */ -bool ietfAttr_list_equals(linked_list_t *list_a, linked_list_t *list_b) -{ - bool result = TRUE; - - /* lists must have the same number of attributes */ - if (list_a->get_count(list_a) != list_b->get_count(list_b)) - { - return FALSE; - } - /* empty lists - no attributes */ - if (list_a->get_count(list_a) == 0) - { - return TRUE; - } - - /* compare two alphabetically-sorted lists */ - { - iterator_t *iterator_a = list_a->create_iterator(list_a, TRUE); - iterator_t *iterator_b = list_b->create_iterator(list_b, TRUE); - ietfAttr_t *attr_a, *attr_b; - - while (iterator_a->iterate(iterator_a, (void **)&attr_a) && - iterator_b->iterate(iterator_b, (void **)&attr_b)) - { - if (attr_a->compare(attr_a, attr_b) != 0) - { - /* we have a mismatch */ - result = FALSE; - break; - } - } - iterator_a->destroy(iterator_a); - iterator_b->destroy(iterator_b); - } - return result; -} - -/* - * Described in header. - */ -void ietfAttr_list_list(linked_list_t *list, FILE *out) -{ - iterator_t *iterator = list->create_iterator(list, TRUE); - ietfAttr_t *attr; - bool first = TRUE; - - while (iterator->iterate(iterator, (void **)&attr)) - { - if (first) - { - first = FALSE; - } - else - { - fprintf(out, ", "); - } - - switch (attr->kind) - { - case IETF_ATTRIBUTE_OCTETS: - case IETF_ATTRIBUTE_STRING: - fprintf(out, "%.*s", (int)attr->value.len, attr->value.ptr); - break; - case IETF_ATTRIBUTE_OID: - { - int oid = known_oid(attr->value); - - if (oid == OID_UNKNOWN) - { - fprintf(out, "0x#B", &attr->value); - } - else - { - fprintf(out, "%s", oid_names[oid]); - } - } - break; - default: - break; - } - } - iterator->destroy(iterator); -} - -/* - * Described in header. - */ -void ietfAttr_list_create_from_string(char *msg, linked_list_t *list) -{ - chunk_t line = { msg, strlen(msg) }; - - while (eat_whitespace(&line)) - { - chunk_t group; - - /* extract the next comma-separated group attribute */ - if (!extract_token(&group, ',', &line)) - { - group = line; - line.len = 0; - } - - /* remove any trailing spaces */ - while (group.len > 0 && *(group.ptr + group.len - 1) == ' ') - { - group.len--; - } - - /* add the group attribute to the list */ - if (group.len > 0) - { - ietfAttr_t *attr = ietfAttr_create(IETF_ATTRIBUTE_STRING, group); - - ietfAttr_add(list, attr); - } - } -} - -/** - * ASN.1 definition of ietfAttrSyntax - */ -static const asn1Object_t ietfAttrSyntaxObjects[] = -{ - { 0, "ietfAttrSyntax", ASN1_SEQUENCE, ASN1_NONE }, /* 0 */ - { 1, "policyAuthority", ASN1_CONTEXT_C_0, ASN1_OPT | - ASN1_BODY }, /* 1 */ - { 1, "end opt", ASN1_EOC, ASN1_END }, /* 2 */ - { 1, "values", ASN1_SEQUENCE, ASN1_LOOP }, /* 3 */ - { 2, "octets", ASN1_OCTET_STRING, ASN1_OPT | - ASN1_BODY }, /* 4 */ - { 2, "end choice", ASN1_EOC, ASN1_END }, /* 5 */ - { 2, "oid", ASN1_OID, ASN1_OPT | - ASN1_BODY }, /* 6 */ - { 2, "end choice", ASN1_EOC, ASN1_END }, /* 7 */ - { 2, "string", ASN1_UTF8STRING, ASN1_OPT | - ASN1_BODY }, /* 8 */ - { 2, "end choice", ASN1_EOC, ASN1_END }, /* 9 */ - { 1, "end loop", ASN1_EOC, ASN1_END } /* 10 */ -}; - -#define IETF_ATTR_OCTETS 4 -#define IETF_ATTR_OID 6 -#define IETF_ATTR_STRING 8 -#define IETF_ATTR_ROOF 11 - -/* - * Described in header. - */ -void ietfAttr_list_create_from_chunk(chunk_t chunk, linked_list_t *list, int level0) -{ - asn1_ctx_t ctx; - chunk_t object; - u_int level; - int objectID = 0; - - asn1_init(&ctx, chunk, level0, FALSE, FALSE); - - while (objectID < IETF_ATTR_ROOF) - { - if (!extract_object(ietfAttrSyntaxObjects, &objectID, &object, &level, &ctx)) - { - return; - } - - switch (objectID) - { - case IETF_ATTR_OCTETS: - case IETF_ATTR_OID: - case IETF_ATTR_STRING: - { - ietfAttribute_t kind = (objectID - IETF_ATTR_OCTETS) / 2; - ietfAttr_t *attr = ietfAttr_create(kind, object); - ietfAttr_add(list, attr); - } - break; - default: - break; - } - objectID++; - } -} - -/* - * Described in header. - */ -chunk_t ietfAttr_list_encode(linked_list_t *list) -{ - chunk_t ietfAttributes; - size_t size = 0; - u_char *pos; - iterator_t *iterator = list->create_iterator(list, TRUE); - ietfAttr_t *attr; - - /* precalculate the total size of all values */ - while (iterator->iterate(iterator, (void **)&attr)) - { - size_t len = attr->value.len; - - size += 1 + (len > 0) + (len >= 128) + (len >= 256) + (len >= 65536) + len; - } - iterator->destroy(iterator); - - pos = build_asn1_object(&ietfAttributes, ASN1_SEQUENCE, size); - - iterator = list->create_iterator(list, TRUE); - while (iterator->iterate(iterator, (void **)&attr)) - { - chunk_t ietfAttribute; - asn1_t type = ASN1_NULL; - - switch (attr->kind) - { - case IETF_ATTRIBUTE_OCTETS: - type = ASN1_OCTET_STRING; - break; - case IETF_ATTRIBUTE_STRING: - type = ASN1_UTF8STRING; - break; - case IETF_ATTRIBUTE_OID: - type = ASN1_OID; - break; - } - ietfAttribute = asn1_simple_object(type, attr->value); - - /* copy ietfAttribute into ietfAttributes chunk */ - memcpy(pos, ietfAttribute.ptr, ietfAttribute.len); - pos += ietfAttribute.len; - free(ietfAttribute.ptr); - } - iterator->destroy(iterator); - - return asn1_wrap(ASN1_SEQUENCE, "m", ietfAttributes); -} - -/* - * Described in header. - */ -void ietfAttr_list_destroy(linked_list_t *list) -{ - list->destroy_offset(list, offsetof(ietfAttr_t, destroy)); -} diff --git a/src/libstrongswan/crypto/ietf_attr_list.h b/src/libstrongswan/crypto/ietf_attr_list.h deleted file mode 100644 index 75407bbf6..000000000 --- a/src/libstrongswan/crypto/ietf_attr_list.h +++ /dev/null @@ -1,89 +0,0 @@ -/** - * @file ietf_attr_list.h - * - * @brief Handling of ietfAttr_t linked lists - * - */ - -/* - * Copyright (C) 2007 Andreas Steffen - * - * Hochschule fuer Technik Rapperswil - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -#ifndef IETF_ATTR_LIST_H_ -#define IETF_ATTR_LIST_H_ - -#include <library.h> -#include <utils/linked_list.h> - - -/** - * @brief Compare two linked lists of ietfAttr_t objects for equality - * - * @param list_a first alphabetically-sorted list - * @param list_b second alphabetically-sorted list - * @return TRUE if equal - * - * @ingroup crypto - */ -bool ietfAttr_list_equals(linked_list_t *list_a, linked_list_t *list_b); - -/** - * @brief Lists a linked list of ietfAttr_t objects - * - * @param list alphabetically-sorted linked list of attributes - @param out output file - * - * @ingroup crypto - */ -void ietfAttr_list_list(linked_list_t *list, FILE *out); - -/** - * @brief Create a linked list of ietfAttr_t objects from a string - * - * @param msg string with comma-separated group names - * @param list alphabetically-sorted linked list of attributes - * - * @ingroup crypto - */ -void ietfAttr_list_create_from_string(char *msg, linked_list_t *list); - -/** - * @brief Create a linked list of ietfAttr_t objects from an ASN.1-coded chunk - * - * @param chunk chunk containing ASN.1-coded attributes - * @param list alphabetically-sorted linked list of attributes - * @param level0 parsing level - */ -void ietfAttr_list_create_from_chunk(chunk_t chunk, linked_list_t *list, int level0); - -/** - * @brief Encode a linked list of ietfAttr_t objects into an ASN.1-coded chunk - * - * @param list alphabetically-sorted linked list of attributes - * @return chunk containing ASN.1-coded attributes - */ -chunk_t ietfAttr_list_encode(linked_list_t *list); - -/** - * @brief Destroys a linked list of ietfAttr_t objects - * - * @param list list to be destroyed - * - * @ingroup crypto - */ -void ietfAttr_list_destroy(linked_list_t *list); - -#endif /* IETF_ATTR_LIST_H_ */ - diff --git a/src/libstrongswan/crypto/ocsp.c b/src/libstrongswan/crypto/ocsp.c deleted file mode 100644 index 4bbec31de..000000000 --- a/src/libstrongswan/crypto/ocsp.c +++ /dev/null @@ -1,934 +0,0 @@ -/** - * @file ocsp.c - * - * @brief Implementation of ocsp_t. - * - */ - -/* Support of the Online Certificate Status Protocol (OCSP) - * - * Copyright (C) 2003 Christoph Gysin, Simon Zwahlen - * Copyright (C) 2007 Andreas Steffen - * - * Hochschule für Technik Rapperswil - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * RCSID $Id$ - */ - -#include <unistd.h> -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <time.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <fcntl.h> - -#include <asn1/oid.h> -#include <asn1/asn1.h> -#include <utils/identification.h> -#include <utils/randomizer.h> -#include <utils/fetcher.h> -#include <debug.h> - -#include "hashers/hasher.h" -#include "rsa/rsa_public_key.h" -#include "certinfo.h" -#include "x509.h" -#include "ocsp.h" - -#define NONCE_LENGTH 16 - -typedef struct private_ocsp_t private_ocsp_t; - -/** - * Private data of a ocsp_t object. - */ -struct private_ocsp_t { - /** - * Public interface for this ocsp object. - */ - ocsp_t public; - - /** - * CA certificate. - */ - x509_t *cacert; - - /** - * Requestor certificate - */ - x509_t *requestor_cert; - - /** - * Linked list of ocsp uris - */ - linked_list_t *uris; - - /** - * Linked list of certinfos to be requested - */ - linked_list_t *certinfos; - - /** - * Nonce required for ocsp request and response - */ - chunk_t nonce; - - /** - * SHA-1 hash over issuer distinguished name - */ - chunk_t authNameID; - - /** - * SHA-1 hash over issuer public key - */ - chunk_t authKeyID; -}; - -ENUM(response_status_names, STATUS_SUCCESSFUL, STATUS_UNAUTHORIZED, - "successful", - "malformed request", - "internal error", - "try later", - "signature required", - "unauthorized" -); - -/* response container */ -typedef struct response_t response_t; - -struct response_t { - chunk_t chunk; - chunk_t tbs; - identification_t *responder_id_name; - chunk_t responder_id_key; - time_t produced_at; - chunk_t responses; - chunk_t nonce; - int algorithm; - chunk_t signature; - x509_t *responder_cert; - - /** - * @brief Destroys the response_t object - * - * @param this response_t to destroy - */ - void (*destroy) (response_t *this); -}; - -/** - * Implements response_t.destroy. - */ -static void response_destroy(response_t *this) -{ - DESTROY_IF(this->responder_id_name); - DESTROY_IF(this->responder_cert); - free(this->chunk.ptr); - free(this); -} - -/** - * Creates a response_t object - */ -static response_t* response_create_from_chunk(chunk_t chunk) -{ - response_t *this = malloc_thing(response_t); - - this->chunk = chunk; - this->tbs = chunk_empty; - this->responder_id_name = NULL; - this->responder_id_key = chunk_empty; - this->produced_at = UNDEFINED_TIME; - this->responses = chunk_empty; - this->nonce = chunk_empty; - this->algorithm = OID_UNKNOWN; - this->signature = chunk_empty; - this->responder_cert = NULL; - - this->destroy = (void (*) (response_t*))response_destroy; - - return this; -} - -/* some OCSP specific prefabricated ASN.1 constants */ - -static u_char ASN1_nonce_oid_str[] = { - 0x06, 0x09, - 0x2B, 0x06, - 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x02 -}; - -static u_char ASN1_response_oid_str[] = { - 0x06, 0x09, - 0x2B, 0x06, - 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x04 -}; - -static u_char ASN1_response_content_str[] = { - 0x04, 0x0D, - 0x30, 0x0B, - 0x06, 0x09, - 0x2B, 0x06, - 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x01 -}; - -static const chunk_t ASN1_nonce_oid = chunk_from_buf(ASN1_nonce_oid_str); -static const chunk_t ASN1_response_oid = chunk_from_buf(ASN1_response_oid_str); -static const chunk_t ASN1_response_content = chunk_from_buf(ASN1_response_content_str); - -/* asn.1 definitions for parsing */ - -static const asn1Object_t ocspResponseObjects[] = { - { 0, "OCSPResponse", ASN1_SEQUENCE, ASN1_NONE }, /* 0 */ - { 1, "responseStatus", ASN1_ENUMERATED, ASN1_BODY }, /* 1 */ - { 1, "responseBytesContext", ASN1_CONTEXT_C_0, ASN1_OPT }, /* 2 */ - { 2, "responseBytes", ASN1_SEQUENCE, ASN1_NONE }, /* 3 */ - { 3, "responseType", ASN1_OID, ASN1_BODY }, /* 4 */ - { 3, "response", ASN1_OCTET_STRING, ASN1_BODY }, /* 5 */ - { 1, "end opt", ASN1_EOC, ASN1_END } /* 6 */ -}; - -#define OCSP_RESPONSE_STATUS 1 -#define OCSP_RESPONSE_TYPE 4 -#define OCSP_RESPONSE 5 -#define OCSP_RESPONSE_ROOF 7 - -static const asn1Object_t basicResponseObjects[] = { - { 0, "BasicOCSPResponse", ASN1_SEQUENCE, ASN1_NONE }, /* 0 */ - { 1, "tbsResponseData", ASN1_SEQUENCE, ASN1_OBJ }, /* 1 */ - { 2, "versionContext", ASN1_CONTEXT_C_0, ASN1_NONE | - ASN1_DEF }, /* 2 */ - { 3, "version", ASN1_INTEGER, ASN1_BODY }, /* 3 */ - { 2, "responderIdContext", ASN1_CONTEXT_C_1, ASN1_OPT }, /* 4 */ - { 3, "responderIdByName", ASN1_SEQUENCE, ASN1_OBJ }, /* 5 */ - { 2, "end choice", ASN1_EOC, ASN1_END }, /* 6 */ - { 2, "responderIdContext", ASN1_CONTEXT_C_2, ASN1_OPT }, /* 7 */ - { 3, "responderIdByKey", ASN1_OCTET_STRING, ASN1_BODY }, /* 8 */ - { 2, "end choice", ASN1_EOC, ASN1_END }, /* 9 */ - { 2, "producedAt", ASN1_GENERALIZEDTIME, ASN1_BODY }, /* 10 */ - { 2, "responses", ASN1_SEQUENCE, ASN1_OBJ }, /* 11 */ - { 2, "responseExtensionsContext", ASN1_CONTEXT_C_1, ASN1_OPT }, /* 12 */ - { 3, "responseExtensions", ASN1_SEQUENCE, ASN1_LOOP }, /* 13 */ - { 4, "extension", ASN1_SEQUENCE, ASN1_NONE }, /* 14 */ - { 5, "extnID", ASN1_OID, ASN1_BODY }, /* 15 */ - { 5, "critical", ASN1_BOOLEAN, ASN1_BODY | - ASN1_DEF }, /* 16 */ - { 5, "extnValue", ASN1_OCTET_STRING, ASN1_BODY }, /* 17 */ - { 4, "end loop", ASN1_EOC, ASN1_END }, /* 18 */ - { 2, "end opt", ASN1_EOC, ASN1_END }, /* 19 */ - { 1, "signatureAlgorithm", ASN1_EOC, ASN1_RAW }, /* 20 */ - { 1, "signature", ASN1_BIT_STRING, ASN1_BODY }, /* 21 */ - { 1, "certsContext", ASN1_CONTEXT_C_0, ASN1_OPT }, /* 22 */ - { 2, "certs", ASN1_SEQUENCE, ASN1_LOOP }, /* 23 */ - { 3, "certificate", ASN1_SEQUENCE, ASN1_RAW }, /* 24 */ - { 2, "end loop", ASN1_EOC, ASN1_END }, /* 25 */ - { 1, "end opt", ASN1_EOC, ASN1_END } /* 26 */ -}; - -#define BASIC_RESPONSE_TBS_DATA 1 -#define BASIC_RESPONSE_VERSION 3 -#define BASIC_RESPONSE_ID_BY_NAME 5 -#define BASIC_RESPONSE_ID_BY_KEY 8 -#define BASIC_RESPONSE_PRODUCED_AT 10 -#define BASIC_RESPONSE_RESPONSES 11 -#define BASIC_RESPONSE_EXT_ID 15 -#define BASIC_RESPONSE_CRITICAL 16 -#define BASIC_RESPONSE_EXT_VALUE 17 -#define BASIC_RESPONSE_ALGORITHM 20 -#define BASIC_RESPONSE_SIGNATURE 21 -#define BASIC_RESPONSE_CERTIFICATE 24 -#define BASIC_RESPONSE_ROOF 27 - -static const asn1Object_t responsesObjects[] = { - { 0, "responses", ASN1_SEQUENCE, ASN1_LOOP }, /* 0 */ - { 1, "singleResponse", ASN1_EOC, ASN1_RAW }, /* 1 */ - { 0, "end loop", ASN1_EOC, ASN1_END } /* 2 */ -}; - -#define RESPONSES_SINGLE_RESPONSE 1 -#define RESPONSES_ROOF 3 - -static const asn1Object_t singleResponseObjects[] = { - { 0, "singleResponse", ASN1_SEQUENCE, ASN1_BODY }, /* 0 */ - { 1, "certID", ASN1_SEQUENCE, ASN1_NONE }, /* 1 */ - { 2, "algorithm", ASN1_EOC, ASN1_RAW }, /* 2 */ - { 2, "issuerNameHash", ASN1_OCTET_STRING, ASN1_BODY }, /* 3 */ - { 2, "issuerKeyHash", ASN1_OCTET_STRING, ASN1_BODY }, /* 4 */ - { 2, "serialNumber", ASN1_INTEGER, ASN1_BODY }, /* 5 */ - { 1, "certStatusGood", ASN1_CONTEXT_S_0, ASN1_OPT }, /* 6 */ - { 1, "end opt", ASN1_EOC, ASN1_END }, /* 7 */ - { 1, "certStatusRevoked", ASN1_CONTEXT_C_1, ASN1_OPT }, /* 8 */ - { 2, "revocationTime", ASN1_GENERALIZEDTIME, ASN1_BODY }, /* 9 */ - { 2, "revocationReason", ASN1_CONTEXT_C_0, ASN1_OPT }, /* 10 */ - { 3, "crlReason", ASN1_ENUMERATED, ASN1_BODY }, /* 11 */ - { 2, "end opt", ASN1_EOC, ASN1_END }, /* 12 */ - { 1, "end opt", ASN1_EOC, ASN1_END }, /* 13 */ - { 1, "certStatusUnknown", ASN1_CONTEXT_S_2, ASN1_OPT }, /* 14 */ - { 1, "end opt", ASN1_EOC, ASN1_END }, /* 15 */ - { 1, "thisUpdate", ASN1_GENERALIZEDTIME, ASN1_BODY }, /* 16 */ - { 1, "nextUpdateContext", ASN1_CONTEXT_C_0, ASN1_OPT }, /* 17 */ - { 2, "nextUpdate", ASN1_GENERALIZEDTIME, ASN1_BODY }, /* 18 */ - { 1, "end opt", ASN1_EOC, ASN1_END }, /* 19 */ - { 1, "singleExtensionsContext", ASN1_CONTEXT_C_1, ASN1_OPT }, /* 20 */ - { 2, "singleExtensions", ASN1_SEQUENCE, ASN1_LOOP }, /* 21 */ - { 3, "extension", ASN1_SEQUENCE, ASN1_NONE }, /* 22 */ - { 4, "extnID", ASN1_OID, ASN1_BODY }, /* 23 */ - { 4, "critical", ASN1_BOOLEAN, ASN1_BODY | - ASN1_DEF }, /* 24 */ - { 4, "extnValue", ASN1_OCTET_STRING, ASN1_BODY }, /* 25 */ - { 2, "end loop", ASN1_EOC, ASN1_END }, /* 26 */ - { 1, "end opt", ASN1_EOC, ASN1_END } /* 27 */ -}; - -#define SINGLE_RESPONSE_ALGORITHM 2 -#define SINGLE_RESPONSE_ISSUER_NAME_HASH 3 -#define SINGLE_RESPONSE_ISSUER_KEY_HASH 4 -#define SINGLE_RESPONSE_SERIAL_NUMBER 5 -#define SINGLE_RESPONSE_CERT_STATUS_GOOD 6 -#define SINGLE_RESPONSE_CERT_STATUS_REVOKED 8 -#define SINGLE_RESPONSE_CERT_STATUS_REVOCATION_TIME 9 -#define SINGLE_RESPONSE_CERT_STATUS_CRL_REASON 11 -#define SINGLE_RESPONSE_CERT_STATUS_UNKNOWN 14 -#define SINGLE_RESPONSE_THIS_UPDATE 16 -#define SINGLE_RESPONSE_NEXT_UPDATE 18 -#define SINGLE_RESPONSE_EXT_ID 23 -#define SINGLE_RESPONSE_CRITICAL 24 -#define SINGLE_RESPONSE_EXT_VALUE 25 -#define SINGLE_RESPONSE_ROOF 28 - -/** - * build requestorName (into TBSRequest) - */ -static chunk_t build_requestor_name(private_ocsp_t *this) -{ - identification_t *requestor_name = this->requestor_cert->get_subject(this->requestor_cert); - - return asn1_wrap(ASN1_CONTEXT_C_1, "m", - asn1_simple_object(ASN1_CONTEXT_C_4, - requestor_name->get_encoding(requestor_name))); -} - -/** - * build request (into requestList) - * no singleRequestExtensions used - */ -static chunk_t build_request(private_ocsp_t *this, certinfo_t *certinfo) -{ - chunk_t serialNumber = certinfo->get_serialNumber(certinfo); - - chunk_t reqCert = asn1_wrap(ASN1_SEQUENCE, "cmmm", - asn1_algorithmIdentifier(OID_SHA1), - asn1_simple_object(ASN1_OCTET_STRING, this->authNameID), - asn1_simple_object(ASN1_OCTET_STRING, this->authKeyID), - asn1_simple_object(ASN1_INTEGER, serialNumber)); - - return asn1_wrap(ASN1_SEQUENCE, "m", reqCert); -} - -/** - * build requestList (into TBSRequest) - */ -static chunk_t build_request_list(private_ocsp_t *this) -{ - chunk_t requestList; - size_t datalen = 0; - linked_list_t *request_list = linked_list_create(); - - { - iterator_t *iterator = this->certinfos->create_iterator(this->certinfos, TRUE); - certinfo_t *certinfo; - - while (iterator->iterate(iterator, (void**)&certinfo)) - { - chunk_t *request = malloc_thing(chunk_t); - - *request = build_request(this, certinfo); - request_list->insert_last(request_list, (void*)request); - datalen += request->len; - } - iterator->destroy(iterator); - } - { - iterator_t *iterator = request_list->create_iterator(request_list, TRUE); - chunk_t *request; - - u_char *pos = build_asn1_object(&requestList, ASN1_SEQUENCE, datalen); - - while (iterator->iterate(iterator, (void**)&request)) - { - memcpy(pos, request->ptr, request->len); - pos += request->len; - free(request->ptr); - free(request); - } - iterator->destroy(iterator); - request_list->destroy(request_list); - } - return requestList; -} - -/** - * build nonce extension (into requestExtensions) - */ -static chunk_t build_nonce_extension(private_ocsp_t *this) -{ - randomizer_t *randomizer = randomizer_create(); - - /* generate a random nonce */ - randomizer->allocate_pseudo_random_bytes(randomizer, NONCE_LENGTH, &this->nonce); - randomizer->destroy(randomizer); - - return asn1_wrap(ASN1_SEQUENCE, "cm", - ASN1_nonce_oid, - asn1_simple_object(ASN1_OCTET_STRING, this->nonce)); -} - -/** - * build requestExtensions (into TBSRequest) - */ -static chunk_t build_request_ext(private_ocsp_t *this) -{ - return asn1_wrap(ASN1_CONTEXT_C_2, "m", - asn1_wrap(ASN1_SEQUENCE, "mm", - build_nonce_extension(this), - asn1_wrap(ASN1_SEQUENCE, "cc", - ASN1_response_oid, - ASN1_response_content - ) - ) - ); -} - -/** - * build TBSRequest (into OCSPRequest) - */ -static chunk_t build_tbs_request(private_ocsp_t *this, bool has_requestor_cert) -{ - /* version is skipped since the default is ok */ - return asn1_wrap(ASN1_SEQUENCE, "mmm", - (has_requestor_cert)? build_requestor_name(this): chunk_empty, - build_request_list(this), - build_request_ext(this)); -} - -/** - * build signature into ocsp request - * gets built only if a request cert with a corresponding private key is found - */ -static chunk_t build_signature(private_ocsp_t *this, chunk_t tbsRequest) -{ - /* TODO */ - return chunk_empty; -} - -/** - * assembles an ocsp request and sets the nonce field in private_ocsp_t to the sent nonce - */ -static chunk_t ocsp_build_request(private_ocsp_t *this) -{ - bool has_requestor_cert; - chunk_t keyid = this->cacert->get_keyid(this->cacert); - chunk_t tbsRequest, signature; - - DBG2("assembling ocsp request"); - DBG2("issuer: '%D'", this->cacert->get_subject(this->cacert)); - DBG2("keyid: %#B", &keyid); - - /* looks for requestor cert and matching private key */ - has_requestor_cert = FALSE; - - /* TODO has_requestor_cert = get_ocsp_requestor_cert(location); */ - - /* build content */ - tbsRequest = build_tbs_request(this, has_requestor_cert); - - /* sign tbsReuqest */ - signature = (has_requestor_cert)? build_signature(this, tbsRequest): chunk_empty; - - return asn1_wrap(ASN1_SEQUENCE, "mm", - tbsRequest, - signature); - - return signature; -} - -/** - * parse a basic OCSP response - */ -static bool ocsp_parse_basic_response(chunk_t blob, int level0, response_t *res) -{ - u_int level, version; - asn1_ctx_t ctx; - bool critical; - chunk_t object; - int objectID = 0; - int extn_oid = OID_UNKNOWN; - - asn1_init(&ctx, blob, level0, FALSE, FALSE); - - while (objectID < BASIC_RESPONSE_ROOF) - { - if (!extract_object(basicResponseObjects, &objectID, &object, &level, &ctx)) - { - return FALSE; - } - - switch (objectID) - { - case BASIC_RESPONSE_TBS_DATA: - res->tbs = object; - break; - case BASIC_RESPONSE_VERSION: - version = (object.len)? (1 + (u_int)*object.ptr) : 1; - if (version != OCSP_BASIC_RESPONSE_VERSION) - { - DBG1("wrong ocsp basic response version (version= %i)", version); - return FALSE; - } - break; - case BASIC_RESPONSE_ID_BY_NAME: - res->responder_id_name = identification_create_from_encoding(ID_DER_ASN1_DN, object); - DBG2(" '%D'", res->responder_id_name); - break; - case BASIC_RESPONSE_ID_BY_KEY: - res->responder_id_key = object; - break; - case BASIC_RESPONSE_PRODUCED_AT: - res->produced_at = asn1totime(&object, ASN1_GENERALIZEDTIME); - break; - case BASIC_RESPONSE_RESPONSES: - res->responses = object; - break; - case BASIC_RESPONSE_EXT_ID: - extn_oid = known_oid(object); - break; - case BASIC_RESPONSE_CRITICAL: - critical = object.len && *object.ptr; - DBG2(" %s", critical? "TRUE" : "FALSE"); - break; - case BASIC_RESPONSE_EXT_VALUE: - if (extn_oid == OID_NONCE) - res->nonce = object; - break; - case BASIC_RESPONSE_ALGORITHM: - res->algorithm = parse_algorithmIdentifier(object, level+1, NULL); - break; - case BASIC_RESPONSE_SIGNATURE: - res->signature = object; - break; - case BASIC_RESPONSE_CERTIFICATE: - { - chunk_t blob = chunk_clone(object); - - res->responder_cert = x509_create_from_chunk(blob, level+1); - } - break; - } - objectID++; - } - return TRUE; -} - -/** - * parse an ocsp response and return the result as a response_t struct - */ -static response_status ocsp_parse_response(response_t *res) -{ - asn1_ctx_t ctx; - chunk_t object; - u_int level; - int objectID = 0; - int ocspResponseType = OID_UNKNOWN; - response_status rStatus = STATUS_INTERNALERROR; - - asn1_init(&ctx, res->chunk, 0, FALSE, FALSE); - - while (objectID < OCSP_RESPONSE_ROOF) - { - if (!extract_object(ocspResponseObjects, &objectID, &object, &level, &ctx)) - { - return STATUS_INTERNALERROR; - } - - switch (objectID) - { - case OCSP_RESPONSE_STATUS: - rStatus = (response_status) *object.ptr; - DBG2(" '%N'", response_status_names, rStatus); - - switch (rStatus) - { - case STATUS_SUCCESSFUL: - break; - case STATUS_MALFORMEDREQUEST: - case STATUS_INTERNALERROR: - case STATUS_TRYLATER: - case STATUS_SIGREQUIRED: - case STATUS_UNAUTHORIZED: - DBG1("unsuccessful ocsp response: server said '%N'", - response_status_names, rStatus); - return rStatus; - default: - return STATUS_INTERNALERROR; - } - break; - case OCSP_RESPONSE_TYPE: - ocspResponseType = known_oid(object); - break; - case OCSP_RESPONSE: - { - switch (ocspResponseType) - { - case OID_BASIC: - if (!ocsp_parse_basic_response(object, level+1, res)) - { - return STATUS_INTERNALERROR; - } - break; - default: - DBG1("ocsp response is not of type BASIC"); - DBG1("ocsp response OID: %#B", &object); - return STATUS_INTERNALERROR; - } - } - break; - } - objectID++; - } - return rStatus; -} - -/** - * Check if the OCSP response has a valid signature - */ -static bool ocsp_valid_response(response_t *res, x509_t *ocsp_cert) -{ - rsa_public_key_t *public_key; - time_t until = UNDEFINED_TIME; - err_t ugh; - hash_algorithm_t algorithm = hasher_algorithm_from_oid(res->algorithm); - - if (algorithm == HASH_UNKNOWN) - { - DBG1("unknown signature algorithm"); - return FALSE; - } - - DBG2("verifying ocsp response signature:"); - DBG2("signer: '%D'", ocsp_cert->get_subject(ocsp_cert)); - DBG2("issuer: '%D'", ocsp_cert->get_issuer(ocsp_cert)); - - ugh = ocsp_cert->is_valid(ocsp_cert, &until); - if (ugh != NULL) - { - DBG1("ocsp signer certificate %s", ugh); - return FALSE; - } - public_key = ocsp_cert->get_public_key(ocsp_cert); - - return public_key->verify_emsa_pkcs1_signature(public_key, algorithm, res->tbs, res->signature) == SUCCESS; -} - -/** - * parse a single OCSP response - */ -static bool ocsp_parse_single_response(private_ocsp_t *this, chunk_t blob, int level0) -{ - u_int level, extn_oid; - asn1_ctx_t ctx; - bool critical; - chunk_t object; - int objectID = 0; - - certinfo_t *certinfo = NULL; - - asn1_init(&ctx, blob, level0, FALSE, FALSE); - - while (objectID < SINGLE_RESPONSE_ROOF) - { - if (!extract_object(singleResponseObjects, &objectID, &object, &level, &ctx)) - { - return FALSE; - } - - switch (objectID) - { - case SINGLE_RESPONSE_ALGORITHM: - if (parse_algorithmIdentifier(object, level+1, NULL) != OID_SHA1) - { - DBG1("only sha-1 hash supported in ocsp single response"); - return FALSE; - } - break; - case SINGLE_RESPONSE_ISSUER_NAME_HASH: - if (!chunk_equals(object, this->authNameID)) - { - DBG1("ocsp single response has wrong issuer name hash"); - return FALSE; - } - break; - case SINGLE_RESPONSE_ISSUER_KEY_HASH: - if (!chunk_equals(object, this->authKeyID)) - { - DBG1("ocsp single response has wrong issuer key hash"); - return FALSE; - } - break; - case SINGLE_RESPONSE_SERIAL_NUMBER: - { - iterator_t *iterator = this->certinfos->create_iterator(this->certinfos, TRUE); - certinfo_t *current_certinfo; - - while (iterator->iterate(iterator, (void**)¤t_certinfo)) - { - if (chunk_equals(object, current_certinfo->get_serialNumber(current_certinfo))) - { - certinfo = current_certinfo; - } - } - iterator->destroy(iterator); - if (certinfo == NULL) - { - DBG1("unrequested serial number in ocsp single response"); - return FALSE; - } - } - break; - case SINGLE_RESPONSE_CERT_STATUS_GOOD: - certinfo->set_status(certinfo, CERT_GOOD); - break; - case SINGLE_RESPONSE_CERT_STATUS_REVOKED: - certinfo->set_status(certinfo, CERT_REVOKED); - break; - case SINGLE_RESPONSE_CERT_STATUS_REVOCATION_TIME: - certinfo->set_revocationTime(certinfo, - asn1totime(&object, ASN1_GENERALIZEDTIME)); - break; - case SINGLE_RESPONSE_CERT_STATUS_CRL_REASON: - certinfo->set_revocationReason(certinfo, - (object.len == 1) ? *object.ptr : REASON_UNSPECIFIED); - break; - case SINGLE_RESPONSE_CERT_STATUS_UNKNOWN: - certinfo->set_status(certinfo, CERT_UNKNOWN); - break; - case SINGLE_RESPONSE_THIS_UPDATE: - certinfo->set_thisUpdate(certinfo, - asn1totime(&object, ASN1_GENERALIZEDTIME)); - break; - case SINGLE_RESPONSE_NEXT_UPDATE: - certinfo->set_nextUpdate(certinfo, - asn1totime(&object, ASN1_GENERALIZEDTIME)); - break; - case SINGLE_RESPONSE_EXT_ID: - extn_oid = known_oid(object); - break; - case SINGLE_RESPONSE_CRITICAL: - critical = object.len && *object.ptr; - DBG2(" %s", critical ? "TRUE" : "FALSE"); - case SINGLE_RESPONSE_EXT_VALUE: - break; - } - objectID++; - } - return TRUE; -} - -/** - * verify and process ocsp response and update the ocsp cache - */ -static void ocsp_process_response(private_ocsp_t *this, response_t *res, credential_store_t *credentials) -{ - x509_t *ocsp_cert = NULL; - - /* parse the ocsp response without looking at the single responses yet */ - response_status status = ocsp_parse_response(res); - - if (status != STATUS_SUCCESSFUL) - { - DBG1("error in ocsp response"); - return; - } - - /* check if there was a nonce in the request */ - if (this->nonce.ptr != NULL && res->nonce.ptr == NULL) - { - DBG1("ocsp response contains no nonce, replay attack possible"); - } - - /* check if the nonces are identical */ - if (res->nonce.ptr != NULL && !chunk_equals(res->nonce, this->nonce)) - { - DBG1("invalid nonce in ocsp response"); - return; - } - - /* check if we received a trusted responder certificate */ - if (res->responder_cert) - { - if (res->responder_cert->is_ocsp_signer(res->responder_cert)) - { - DBG2("received certificate is ocsp signer"); - if (credentials->is_trusted(credentials, "OCSP signing", res->responder_cert)) - { - DBG1("received ocsp signer certificate is trusted"); - ocsp_cert = credentials->add_auth_certificate(credentials, - res->responder_cert, AUTH_OCSP); - res->responder_cert = NULL; - } - else - { - DBG1("received ocsp signer certificate is not trusted - rejected"); - } - } - else - { - DBG1("received certificate is no ocsp signer - rejected"); - } - } - - /* if we didn't receive a trusted responder cert, search the credential store */ - if (ocsp_cert == NULL) - { - ocsp_cert = credentials->get_auth_certificate(credentials, - AUTH_OCSP|AUTH_CA, res->responder_id_name); - if (ocsp_cert == NULL) - { - DBG1("no ocsp signer certificate found"); - return; - } - } - - /* check the response signature */ - if (!ocsp_valid_response(res, ocsp_cert)) - { - DBG1("ocsp response signature is invalid"); - return; - } - DBG2("ocsp response signature is valid"); - - /* now parse the single responses one at a time */ - { - u_int level; - asn1_ctx_t ctx; - chunk_t object; - int objectID = 0; - - asn1_init(&ctx, res->responses, 0, FALSE, FALSE); - - while (objectID < RESPONSES_ROOF) - { - if (!extract_object(responsesObjects, &objectID, &object, &level, &ctx)) - { - return; - } - if (objectID == RESPONSES_SINGLE_RESPONSE) - { - ocsp_parse_single_response(this, object, level+1); - } - objectID++; - } - } -} - -/** - * Implements ocsp_t.fetch. - */ -static void fetch(private_ocsp_t *this, certinfo_t *certinfo, credential_store_t *credentials) -{ - chunk_t request; - response_t *response = NULL; - - if (this->uris->get_count(this->uris) == 0) - { - return; - } - this->certinfos->insert_last(this->certinfos, (void*)certinfo); - - request = ocsp_build_request(this); - DBG3("ocsp request: %B", &request); - { - iterator_t *iterator = this->uris->create_iterator(this->uris, TRUE); - identification_t *uri; - - while (iterator->iterate(iterator, (void**)&uri)) - { - fetcher_t *fetcher; - char uri_string[BUF_LEN]; - chunk_t uri_chunk = uri->get_encoding(uri); - chunk_t response_chunk; - - snprintf(uri_string, BUF_LEN, "%.*s", uri_chunk.len, uri_chunk.ptr); - fetcher = fetcher_create(uri_string); - - response_chunk = fetcher->post(fetcher, "application/ocsp-request", request); - fetcher->destroy(fetcher); - if (response_chunk.ptr != NULL) - { - response = response_create_from_chunk(response_chunk); - break; - } - } - iterator->destroy(iterator); - } - free(request.ptr); - - if (response == NULL) - { - return; - } - DBG3("ocsp response: %B", &response->chunk); - ocsp_process_response(this, response, credentials); - response->destroy(response); -} - -/** - * Implements ocsp_t.destroy. - */ -static void destroy(private_ocsp_t *this) -{ - this->certinfos->destroy(this->certinfos); - free(this->authNameID.ptr); - free(this->nonce.ptr); - free(this); -} - -/* - * Described in header. - */ -ocsp_t *ocsp_create(x509_t *cacert, linked_list_t *uris) -{ - private_ocsp_t *this = malloc_thing(private_ocsp_t); - - /* initialize */ - this->cacert = cacert; - this->uris = uris; - this->certinfos = linked_list_create(); - this->nonce = chunk_empty; - this->authKeyID = cacert->get_subjectKeyID(cacert); - { - hasher_t *hasher = hasher_create(HASH_SHA1); - identification_t *issuer = cacert->get_subject(cacert); - - hasher->allocate_hash(hasher, issuer->get_encoding(issuer), - &this->authNameID); - hasher->destroy(hasher); - } - - /* public functions */ - this->public.fetch = (void (*) (ocsp_t*,certinfo_t*,credential_store_t*))fetch; - this->public.destroy = (void (*) (ocsp_t*))destroy; - - return &this->public; -} diff --git a/src/libstrongswan/crypto/ocsp.h b/src/libstrongswan/crypto/ocsp.h deleted file mode 100644 index e468bb8be..000000000 --- a/src/libstrongswan/crypto/ocsp.h +++ /dev/null @@ -1,89 +0,0 @@ -/** - * @file ocsp.h - * - * @brief Interface of ocsp_t - * - */ - -/* Support of the Online Certificate Status Protocol (OCSP) Support - * - * Copyright (C) 2003 Christoph Gysin, Simon Zwahlen - * Copyright (C) 2007 Andreas Steffen - * - * Hochschule fuer Technik Rapperswil, Switzerland - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * RCSID $Id$ - */ - -#ifndef OCSP_H_ -#define OCSP_H_ - -typedef struct ocsp_t ocsp_t; - -#include <credential_store.h> -#include <utils/linked_list.h> - -#include "certinfo.h" - -/* constants */ -#define OCSP_BASIC_RESPONSE_VERSION 1 -#define OCSP_DEFAULT_VALID_TIME 120 /* validity of one-time response in seconds */ -#define OCSP_WARNING_INTERVAL 2 /* days */ - -/* OCSP response status */ -typedef enum { - STATUS_SUCCESSFUL = 0, - STATUS_MALFORMEDREQUEST = 1, - STATUS_INTERNALERROR = 2, - STATUS_TRYLATER = 3, - STATUS_SIGREQUIRED = 5, - STATUS_UNAUTHORIZED= 6 -} response_status; - -/** - * @brief Online Certficate Status Protocol (OCSP) - * - * @ingroup transforms - */ -struct ocsp_t { - - /** - * @brief Fetches the actual certificate status via OCSP - * - * @param uris linked list of ocsp uris - * @param certinfo certificate status info to be updated - * @param credentials credential store needed for trust path verification - */ - void (*fetch) (ocsp_t *this, certinfo_t *certinfo, credential_store_t *credentials); - - /** - * @brief Destroys the ocsp_t object. - * - * @param this ocsp object to destroy - */ - void (*destroy) (ocsp_t *this); - -}; - -/** - * @brief Create an ocsp_t object. - * - * @param cacert ca certificate - * @param uris linked list of ocsp uris - * @return created ocsp_t object - * - * @ingroup transforms - */ -ocsp_t *ocsp_create(x509_t *cacert, linked_list_t *uris); - -#endif /* OCSP_H_ */ diff --git a/src/libstrongswan/crypto/pkcs7.c b/src/libstrongswan/crypto/pkcs7.c deleted file mode 100644 index 48d3e2d78..000000000 --- a/src/libstrongswan/crypto/pkcs7.c +++ /dev/null @@ -1,1077 +0,0 @@ -/** - * @file pkcs7.c - * - * @brief Implementation of pkcs7_t. - * - */ - -/* - * Copyright (C) 2005 Jan Hutter, Martin Willi - * Copyright (C) 2002-2008 Andreas Steffen - * - * Hochschule fuer Technik Rapperswil, Switzerland - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * RCSID $Id: pkcs7.c 3438 2008-02-02 00:29:03Z andreas $ - */ - -#include <stdlib.h> -#include <string.h> - -#include <library.h> -#include "debug.h" - -#include <asn1/asn1.h> -#include <asn1/oid.h> -#include <crypto/x509.h> -#include <crypto/pkcs9.h> -#include <crypto/hashers/hasher.h> -#include <crypto/crypters/crypter.h> -#include <crypto/rsa/rsa_public_key.h> -#include <utils/randomizer.h> -#include <utils/linked_list.h> - -#include "pkcs7.h" - -typedef struct private_pkcs7_t private_pkcs7_t; - -/** - * Private data of a pkcs7_t object. - */ -struct private_pkcs7_t { - /** - * Public interface for this certificate. - */ - pkcs7_t public; - - /** - * contentInfo type - */ - int type; - - /** - * ASN.1 encoded content - */ - chunk_t content; - - /** - * Has the content already been parsed? - */ - bool parsed; - - /** - * ASN.1 parsing start level - */ - u_int level; - - /** - * retrieved data - */ - chunk_t data; - - /** - * ASN.1 encoded attributes - */ - pkcs9_t *attributes; - - /** - * Linked list of X.509 certificates - */ - linked_list_t *certs; -}; - -/** - * ASN.1 definition of the PKCS#7 ContentInfo type - */ -static const asn1Object_t contentInfoObjects[] = { - { 0, "contentInfo", ASN1_SEQUENCE, ASN1_NONE }, /* 0 */ - { 1, "contentType", ASN1_OID, ASN1_BODY }, /* 1 */ - { 1, "content", ASN1_CONTEXT_C_0, ASN1_OPT | - ASN1_BODY }, /* 2 */ - { 1, "end opt", ASN1_EOC, ASN1_END } /* 3 */ -}; - -#define PKCS7_INFO_TYPE 1 -#define PKCS7_INFO_CONTENT 2 -#define PKCS7_INFO_ROOF 4 - -/** - * ASN.1 definition of the PKCS#7 signedData type - */ -static const asn1Object_t signedDataObjects[] = { - { 0, "signedData", ASN1_SEQUENCE, ASN1_NONE }, /* 0 */ - { 1, "version", ASN1_INTEGER, ASN1_BODY }, /* 1 */ - { 1, "digestAlgorithms", ASN1_SET, ASN1_LOOP }, /* 2 */ - { 2, "algorithm", ASN1_EOC, ASN1_RAW }, /* 3 */ - { 1, "end loop", ASN1_EOC, ASN1_END }, /* 4 */ - { 1, "contentInfo", ASN1_EOC, ASN1_RAW }, /* 5 */ - { 1, "certificates", ASN1_CONTEXT_C_0, ASN1_OPT | - ASN1_LOOP }, /* 6 */ - { 2, "certificate", ASN1_SEQUENCE, ASN1_OBJ }, /* 7 */ - { 1, "end opt or loop", ASN1_EOC, ASN1_END }, /* 8 */ - { 1, "crls", ASN1_CONTEXT_C_1, ASN1_OPT | - ASN1_LOOP }, /* 9 */ - { 2, "crl", ASN1_SEQUENCE, ASN1_OBJ }, /* 10 */ - { 1, "end opt or loop", ASN1_EOC, ASN1_END }, /* 11 */ - { 1, "signerInfos", ASN1_SET, ASN1_LOOP }, /* 12 */ - { 2, "signerInfo", ASN1_SEQUENCE, ASN1_NONE }, /* 13 */ - { 3, "version", ASN1_INTEGER, ASN1_BODY }, /* 14 */ - { 3, "issuerAndSerialNumber", ASN1_SEQUENCE, ASN1_BODY }, /* 15 */ - { 4, "issuer", ASN1_SEQUENCE, ASN1_OBJ }, /* 16 */ - { 4, "serial", ASN1_INTEGER, ASN1_BODY }, /* 17 */ - { 3, "digestAlgorithm", ASN1_EOC, ASN1_RAW }, /* 18 */ - { 3, "authenticatedAttributes", ASN1_CONTEXT_C_0, ASN1_OPT | - ASN1_OBJ }, /* 19 */ - { 3, "end opt", ASN1_EOC, ASN1_END }, /* 20 */ - { 3, "digestEncryptionAlgorithm", ASN1_EOC, ASN1_RAW }, /* 21 */ - { 3, "encryptedDigest", ASN1_OCTET_STRING, ASN1_BODY }, /* 22 */ - { 3, "unauthenticatedAttributes", ASN1_CONTEXT_C_1, ASN1_OPT }, /* 23 */ - { 3, "end opt", ASN1_EOC, ASN1_END }, /* 24 */ - { 1, "end loop", ASN1_EOC, ASN1_END } /* 25 */ -}; - -#define PKCS7_DIGEST_ALG 3 -#define PKCS7_SIGNED_CONTENT_INFO 5 -#define PKCS7_SIGNED_CERT 7 -#define PKCS7_SIGNER_INFO 13 -#define PKCS7_SIGNED_ISSUER 16 -#define PKCS7_SIGNED_SERIAL_NUMBER 17 -#define PKCS7_DIGEST_ALGORITHM 18 -#define PKCS7_AUTH_ATTRIBUTES 19 -#define PKCS7_DIGEST_ENC_ALGORITHM 21 -#define PKCS7_ENCRYPTED_DIGEST 22 -#define PKCS7_SIGNED_ROOF 26 - -/** - * ASN.1 definition of the PKCS#7 envelopedData type - */ -static const asn1Object_t envelopedDataObjects[] = { - { 0, "envelopedData", ASN1_SEQUENCE, ASN1_NONE }, /* 0 */ - { 1, "version", ASN1_INTEGER, ASN1_BODY }, /* 1 */ - { 1, "recipientInfos", ASN1_SET, ASN1_LOOP }, /* 2 */ - { 2, "recipientInfo", ASN1_SEQUENCE, ASN1_BODY }, /* 3 */ - { 3, "version", ASN1_INTEGER, ASN1_BODY }, /* 4 */ - { 3, "issuerAndSerialNumber", ASN1_SEQUENCE, ASN1_BODY }, /* 5 */ - { 4, "issuer", ASN1_SEQUENCE, ASN1_OBJ }, /* 6 */ - { 4, "serial", ASN1_INTEGER, ASN1_BODY }, /* 7 */ - { 3, "encryptionAlgorithm", ASN1_EOC, ASN1_RAW }, /* 8 */ - { 3, "encryptedKey", ASN1_OCTET_STRING, ASN1_BODY }, /* 9 */ - { 1, "end loop", ASN1_EOC, ASN1_END }, /* 10 */ - { 1, "encryptedContentInfo", ASN1_SEQUENCE, ASN1_OBJ }, /* 11 */ - { 2, "contentType", ASN1_OID, ASN1_BODY }, /* 12 */ - { 2, "contentEncryptionAlgorithm", ASN1_EOC, ASN1_RAW }, /* 13 */ - { 2, "encryptedContent", ASN1_CONTEXT_S_0, ASN1_BODY } /* 14 */ -}; - -#define PKCS7_ENVELOPED_VERSION 1 -#define PKCS7_RECIPIENT_INFO_VERSION 4 -#define PKCS7_ISSUER 6 -#define PKCS7_SERIAL_NUMBER 7 -#define PKCS7_ENCRYPTION_ALG 8 -#define PKCS7_ENCRYPTED_KEY 9 -#define PKCS7_CONTENT_TYPE 12 -#define PKCS7_CONTENT_ENC_ALGORITHM 13 -#define PKCS7_ENCRYPTED_CONTENT 14 -#define PKCS7_ENVELOPED_ROOF 15 - -/** - * PKCS7 contentInfo OIDs - */ -static u_char ASN1_pkcs7_data_oid_str[] = { - 0x06, 0x09, - 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x01 -}; - -static u_char ASN1_pkcs7_signed_data_oid_str[] = { - 0x06, 0x09, - 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x02 -}; - -static u_char ASN1_pkcs7_enveloped_data_oid_str[] = { - 0x06, 0x09, - 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x03 -}; - -static u_char ASN1_pkcs7_signed_enveloped_data_oid_str[] = { - 0x06, 0x09, - 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x04 -}; - -static u_char ASN1_pkcs7_digested_data_oid_str[] = { - 0x06, 0x09, - 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x05 -}; - -static char ASN1_pkcs7_encrypted_data_oid_str[] = { - 0x06, 0x09, - 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x06 -}; - -static const chunk_t ASN1_pkcs7_data_oid = - chunk_from_buf(ASN1_pkcs7_data_oid_str); -static const chunk_t ASN1_pkcs7_signed_data_oid = - chunk_from_buf(ASN1_pkcs7_signed_data_oid_str); -static const chunk_t ASN1_pkcs7_enveloped_data_oid = - chunk_from_buf(ASN1_pkcs7_enveloped_data_oid_str); -static const chunk_t ASN1_pkcs7_signed_enveloped_data_oid = - chunk_from_buf(ASN1_pkcs7_signed_enveloped_data_oid_str); -static const chunk_t ASN1_pkcs7_digested_data_oid = - chunk_from_buf(ASN1_pkcs7_digested_data_oid_str); -static const chunk_t ASN1_pkcs7_encrypted_data_oid = - chunk_from_buf(ASN1_pkcs7_encrypted_data_oid_str); - -/** - * 3DES and DES encryption OIDs - */ -static u_char ASN1_3des_ede_cbc_oid_str[] = { - 0x06, 0x08, - 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x03, 0x07 -}; - -static u_char ASN1_des_cbc_oid_str[] = { - 0x06, 0x05, - 0x2B, 0x0E, 0x03, 0x02, 0x07 -}; - -static const chunk_t ASN1_3des_ede_cbc_oid = - chunk_from_buf(ASN1_3des_ede_cbc_oid_str); -static const chunk_t ASN1_des_cbc_oid = - chunk_from_buf(ASN1_des_cbc_oid_str); - -/** - * Implements pkcs7_t.is_data. - */ -static bool is_data(private_pkcs7_t *this) -{ - return this->type == OID_PKCS7_DATA; -} - -/** - * Implements pkcs7_t.is_signedData. - */ -static bool is_signedData(private_pkcs7_t *this) -{ - return this->type == OID_PKCS7_SIGNED_DATA; -} - -/** - * Implements pkcs7_t.is_envelopedData. - */ -static bool is_envelopedData(private_pkcs7_t *this) -{ - return this->type == OID_PKCS7_ENVELOPED_DATA; -} - -/** - * Check whether to abort the requested parsing - */ -static bool abort_parsing(private_pkcs7_t *this, int type) -{ - if (this->type != type) - { - DBG1("pkcs7 content to be parsed is not of type '%s'", - oid_names[type]); - return TRUE; - } - if (this->parsed) - { - DBG1("pkcs7 content has already been parsed"); - return TRUE; - } - this->parsed = TRUE; - return FALSE; -} - -/** - * Implements pkcs7_t.parse_data. - */ -static bool parse_data(private_pkcs7_t *this) -{ - chunk_t data = this->content; - - if (abort_parsing(this, OID_PKCS7_DATA)) - { - return FALSE; - } - if (data.len == 0) - { - this->data = chunk_empty; - return TRUE; - } - if (parse_asn1_simple_object(&data, ASN1_OCTET_STRING, this->level, "data")) - { - this->data = chunk_clone(data); - return TRUE; - } - else - { - return FALSE; - } -} - -/** - * Implements pkcs7_t.parse_signedData. - */ -static bool parse_signedData(private_pkcs7_t *this, x509_t *cacert) -{ - asn1_ctx_t ctx; - chunk_t object; - u_int level; - int objectID = 0; - - int digest_alg = OID_UNKNOWN; - int enc_alg = OID_UNKNOWN; - int signerInfos = 0; - - chunk_t encrypted_digest = chunk_empty; - - if (abort_parsing(this, OID_PKCS7_SIGNED_DATA)) - { - return FALSE; - } - - asn1_init(&ctx, this->content, this->level, FALSE, FALSE); - - while (objectID < PKCS7_SIGNED_ROOF) - { - if (!extract_object(signedDataObjects, &objectID, &object, &level, &ctx)) - { - return FALSE; - } - - switch (objectID) - { - case PKCS7_DIGEST_ALG: - digest_alg = parse_algorithmIdentifier(object, level, NULL); - break; - case PKCS7_SIGNED_CONTENT_INFO: - { - chunk_t pureData; - pkcs7_t *data = pkcs7_create_from_chunk(object, level+1); - - if (data == NULL) - { - return FALSE; - } - if (!data->parse_data(data)) - { - data->destroy(data); - return FALSE; - } - pureData = data->get_data(data); - this->data = (pureData.len)? chunk_clone(pureData) : chunk_empty; - data->destroy(data); - } - break; - case PKCS7_SIGNED_CERT: - { - x509_t *cert = x509_create_from_chunk(chunk_clone(object), level+1); - - if (cert) - { - this->certs->insert_last(this->certs, (void*)cert); - } - } - break; - case PKCS7_SIGNER_INFO: - signerInfos++; - DBG2(" signer #%d", signerInfos); - break; - case PKCS7_SIGNED_ISSUER: - { - identification_t *issuer; - - issuer = identification_create_from_encoding(ID_DER_ASN1_DN, object); - DBG2(" '%D'", issuer); - issuer->destroy(issuer); - } - break; - case PKCS7_AUTH_ATTRIBUTES: - *object.ptr = ASN1_SET; - this->attributes = pkcs9_create_from_chunk(object, level+1); - *object.ptr = ASN1_CONTEXT_C_0; - break; - case PKCS7_DIGEST_ALGORITHM: - digest_alg = parse_algorithmIdentifier(object, level, NULL); - break; - case PKCS7_DIGEST_ENC_ALGORITHM: - enc_alg = parse_algorithmIdentifier(object, level, NULL); - break; - case PKCS7_ENCRYPTED_DIGEST: - encrypted_digest = object; - } - objectID++; - } - - /* check the signature only if a cacert is available */ - if (cacert != NULL) - { - hash_algorithm_t algorithm = hasher_algorithm_from_oid(digest_alg); - rsa_public_key_t *signer = cacert->get_public_key(cacert); - - if (signerInfos == 0) - { - DBG1("no signerInfo object found"); - return FALSE; - } - else if (signerInfos > 1) - { - DBG1("more than one signerInfo object found"); - return FALSE; - } - if (this->attributes == NULL) - { - DBG1("no authenticatedAttributes object found"); - return FALSE; - } - if (enc_alg != OID_RSA_ENCRYPTION) - { - DBG1("only RSA digest encryption supported"); - return FALSE; - } - if (signer->verify_emsa_pkcs1_signature(signer, algorithm, - this->attributes->get_encoding(this->attributes), encrypted_digest) != SUCCESS) - { - DBG1("invalid digest signature"); - return FALSE; - } - else - { - DBG2("digest signature is valid"); - } - if (this->data.ptr != NULL) - { - chunk_t messageDigest = this->attributes->get_messageDigest(this->attributes); - - if (messageDigest.ptr == NULL) - { - DBG1("messageDigest attribute not found"); - return FALSE; - } - else - { - hasher_t *hasher = hasher_create(algorithm); - chunk_t hash; - bool valid; - - hasher->allocate_hash(hasher, this->data, &hash); - hasher->destroy(hasher); - DBG3("hash: %B", &hash); - - valid = chunk_equals(messageDigest, hash); - free(messageDigest.ptr); - free(hash.ptr); - if (valid) - { - DBG2("messageDigest is valid"); - } - else - { - DBG1("invalid messageDigest"); - return FALSE; - } - } - } - } - return TRUE; -} - -/** - * Parse PKCS#7 envelopedData content - */ -static bool parse_envelopedData(private_pkcs7_t *this, chunk_t serialNumber, - rsa_private_key_t *key) -{ - asn1_ctx_t ctx; - chunk_t object; - u_int level; - int objectID = 0; - - chunk_t iv = chunk_empty; - chunk_t symmetric_key = chunk_empty; - chunk_t encrypted_content = chunk_empty; - - crypter_t *crypter = NULL; - - if (abort_parsing(this, OID_PKCS7_ENVELOPED_DATA)) - { - return FALSE; - } - - asn1_init(&ctx, this->content, this->level, FALSE, FALSE); - - while (objectID < PKCS7_ENVELOPED_ROOF) - { - if (!extract_object(envelopedDataObjects, &objectID, &object, &level, &ctx)) - { - goto failed; - } - - switch (objectID) - { - case PKCS7_ENVELOPED_VERSION: - if (*object.ptr != 0) - { - DBG1("envelopedData version is not 0"); - goto failed; - } - break; - case PKCS7_RECIPIENT_INFO_VERSION: - if (*object.ptr != 0) - { - DBG1("recipient info version is not 0"); - goto failed; - } - break; - case PKCS7_ISSUER: - { - identification_t *issuer; - - issuer = identification_create_from_encoding(ID_DER_ASN1_DN, object); - DBG2(" '%D'", issuer); - issuer->destroy(issuer); - } - break; - case PKCS7_SERIAL_NUMBER: - if (!chunk_equals(serialNumber, object)) - { - DBG1("serial numbers do not match"); - goto failed; - } - break; - case PKCS7_ENCRYPTION_ALG: - { - int alg = parse_algorithmIdentifier(object, level, NULL); - - if (alg != OID_RSA_ENCRYPTION) - { - DBG1("only rsa encryption supported"); - goto failed; - } - } - break; - case PKCS7_ENCRYPTED_KEY: - if (key->pkcs1_decrypt(key, object, &symmetric_key) != SUCCESS) - { - DBG1("symmetric key could not be decrypted with rsa"); - goto failed; - } - DBG4("symmetric key : %B", &symmetric_key); - break; - case PKCS7_CONTENT_TYPE: - if (known_oid(object) != OID_PKCS7_DATA) - { - DBG1("encrypted content not of type pkcs7 data"); - goto failed; - } - break; - case PKCS7_CONTENT_ENC_ALGORITHM: - { - int alg = parse_algorithmIdentifier(object, level, &iv); - - switch (alg) - { - case OID_DES_CBC: - crypter = crypter_create(ENCR_DES, 0); - break; - case OID_3DES_EDE_CBC: - crypter = crypter_create(ENCR_3DES, 0); - break; - default: - DBG1("Only DES and 3DES supported for symmetric encryption"); - goto failed; - } - if (symmetric_key.len != crypter->get_key_size(crypter)) - { - DBG1("symmetric key has wrong length"); - goto failed; - } - if (!parse_asn1_simple_object(&iv, ASN1_OCTET_STRING, level+1, "IV")) - { - DBG1("IV could not be parsed"); - goto failed; - } - if (iv.len != crypter->get_block_size(crypter)) - { - DBG1("IV has wrong length"); - goto failed; - } - } - break; - case PKCS7_ENCRYPTED_CONTENT: - encrypted_content = object; - break; - } - objectID++; - } - - /* decrypt the content */ - crypter->set_key(crypter, symmetric_key); - crypter->decrypt(crypter, encrypted_content, iv, &this->data); - DBG3("decrypted content with padding: %B", &this->data); - - /* remove the padding */ - { - u_char *pos = this->data.ptr + this->data.len - 1; - u_char pattern = *pos; - size_t padding = pattern; - - if (padding > this->data.len) - { - DBG1("padding greater than data length"); - goto failed; - } - this->data.len -= padding; - - while (padding-- > 0) - { - if (*pos-- != pattern) - { - DBG1("wrong padding pattern"); - goto failed; - } - } - } - crypter->destroy(crypter); - free(symmetric_key.ptr); - return TRUE; - -failed: - DESTROY_IF(crypter); - free(symmetric_key.ptr); - chunk_free(&this->data); - return FALSE; -} - -/** - * Implements pkcs7_t.get_data. - */ -static chunk_t get_data(private_pkcs7_t *this) -{ - return this->data; -} - -/** - * Implements pkcs7_t.get_contentInfo. - */ -static chunk_t get_contentInfo(private_pkcs7_t *this) -{ - chunk_t content_type; - - /* select DER-encoded OID for pkcs7_contentInfo type */ - switch(this->type) - { - case OID_PKCS7_DATA: - content_type = ASN1_pkcs7_data_oid; - break; - case OID_PKCS7_SIGNED_DATA: - content_type = ASN1_pkcs7_signed_data_oid; - break; - case OID_PKCS7_ENVELOPED_DATA: - content_type = ASN1_pkcs7_enveloped_data_oid; - break; - case OID_PKCS7_SIGNED_ENVELOPED_DATA: - content_type = ASN1_pkcs7_signed_enveloped_data_oid; - break; - case OID_PKCS7_DIGESTED_DATA: - content_type = ASN1_pkcs7_digested_data_oid; - break; - case OID_PKCS7_ENCRYPTED_DATA: - content_type = ASN1_pkcs7_encrypted_data_oid; - break; - case OID_UNKNOWN: - default: - DBG1("invalid pkcs7 contentInfo type"); - return chunk_empty; - } - - return (this->content.ptr == NULL) - ? asn1_simple_object(ASN1_SEQUENCE, content_type) - : asn1_wrap(ASN1_SEQUENCE, "cm", - content_type, - asn1_simple_object(ASN1_CONTEXT_C_0, this->content) - ); -} - -/** - * Implements pkcs7_t.create_certificate_iterator - */ -static iterator_t *create_certificate_iterator(const private_pkcs7_t *this) -{ - return this->certs->create_iterator(this->certs, TRUE); -} - -/** - * Implements pkcs7_t.set_certificate - */ -static void set_certificate(private_pkcs7_t *this, x509_t *cert) -{ - if (cert) - { - /* TODO the certificate is currently not cloned */ - this->certs->insert_last(this->certs, cert); - } -} - -/** - * Implements pkcs7_t.set_attributes - */ -static void set_attributes(private_pkcs7_t *this, pkcs9_t *attributes) -{ - this->attributes = attributes; -} - -/** - * build a DER-encoded issuerAndSerialNumber object - */ -chunk_t pkcs7_build_issuerAndSerialNumber(x509_t *cert) -{ - identification_t *issuer = cert->get_issuer(cert); - - return asn1_wrap(ASN1_SEQUENCE, "cm", - issuer->get_encoding(issuer), - asn1_simple_object(ASN1_INTEGER, cert->get_serialNumber(cert))); -} - -/** - * Implements pkcs7_t.build_envelopedData. - */ -bool build_envelopedData(private_pkcs7_t *this, x509_t *cert, - encryption_algorithm_t alg) -{ - chunk_t iv, symmetricKey, in, out, alg_oid; - crypter_t *crypter; - - /* select OID of symmetric encryption algorithm */ - switch (alg) - { - case ENCR_DES: - alg_oid = ASN1_des_cbc_oid; - break; - case ENCR_3DES: - alg_oid = ASN1_3des_ede_cbc_oid; - break; - default: - DBG1(" encryption algorithm %N not supported", - encryption_algorithm_names, alg); - return FALSE; - } - - crypter = crypter_create(alg, 0); - if (crypter == NULL) - { - DBG1(" could not create crypter for algorithm %N", - encryption_algorithm_names, alg); - return FALSE; - } - - /* generate a true random symmetric encryption key - * and a pseudo-random iv - */ - { - randomizer_t *randomizer = randomizer_create(); - - randomizer->allocate_random_bytes(randomizer, - crypter->get_key_size(crypter), &symmetricKey); - DBG4(" symmetric encryption key: %B", &symmetricKey); - - randomizer->allocate_pseudo_random_bytes(randomizer, - crypter->get_block_size(crypter), &iv); - DBG4(" initialization vector: %B", &iv); - - randomizer->destroy(randomizer); - } - - /* pad the data so that the total length becomes - * a multiple of the block size - */ - { - size_t block_size = crypter->get_block_size(crypter); - size_t padding = block_size - this->data.len % block_size; - - in.len = this->data.len + padding; - in.ptr = malloc(in.len); - - DBG2(" padding %d bytes of data to multiple block size of %d bytes", - (int)this->data.len, (int)in.len); - - /* copy data */ - memcpy(in.ptr, this->data.ptr, this->data.len); - /* append padding */ - memset(in.ptr + this->data.len, padding, padding); - } - DBG3(" padded unencrypted data: %B", &in); - - /* symmetric encryption of data object */ - crypter->set_key(crypter, symmetricKey); - crypter->encrypt(crypter, in, iv, &out); - crypter->destroy(crypter); - chunk_free_randomized(&in); - DBG3(" encrypted data: %B", &out); - - /* build pkcs7 enveloped data object */ - { - chunk_t contentEncryptionAlgorithm = asn1_wrap(ASN1_SEQUENCE, "cm", - alg_oid, - asn1_wrap(ASN1_OCTET_STRING, "m", iv)); - - chunk_t encryptedContentInfo = asn1_wrap(ASN1_SEQUENCE, "cmm", - ASN1_pkcs7_data_oid, - contentEncryptionAlgorithm, - asn1_wrap(ASN1_CONTEXT_S_0, "m", out)); - - chunk_t wrappedKey, encryptedKey, recipientInfo; - - rsa_public_key_t *public_key = cert->get_public_key(cert); - - public_key->pkcs1_encrypt(public_key, symmetricKey, &wrappedKey); - chunk_free_randomized(&symmetricKey); - - encryptedKey = asn1_wrap(ASN1_OCTET_STRING, "m", wrappedKey); - - recipientInfo = asn1_wrap(ASN1_SEQUENCE, "cmcm", - ASN1_INTEGER_0, - pkcs7_build_issuerAndSerialNumber(cert), - asn1_algorithmIdentifier(OID_RSA_ENCRYPTION), - encryptedKey); - - this->content = asn1_wrap(ASN1_SEQUENCE, "cmm", - ASN1_INTEGER_0, - asn1_wrap(ASN1_SET, "m", recipientInfo), - encryptedContentInfo); - this->type = OID_PKCS7_ENVELOPED_DATA; - } - return TRUE; -} - -/** - * Implements pkcs7_t.build_signedData. - */ -bool build_signedData(private_pkcs7_t *this, rsa_private_key_t *private_key, - hash_algorithm_t alg) -{ - int signature_oid = hasher_signature_algorithm_to_oid(alg); - chunk_t authenticatedAttributes = chunk_empty; - chunk_t encryptedDigest = chunk_empty; - chunk_t signerInfo; - x509_t *cert; - - if (this->certs->get_first(this->certs, (void**)&cert) != SUCCESS) - { - DBG1(" no pkcs7 signer certificate found"); - return FALSE; - } - - if (this->attributes != NULL) - { - if (this->data.ptr != NULL) - { - /* take the current time as signingTime */ - time_t now = time(NULL); - chunk_t signingTime = timetoasn1(&now, ASN1_UTCTIME); - - chunk_t messageDigest, attributes; - hasher_t *hasher = hasher_create(alg); - - hasher->allocate_hash(hasher, this->data, &messageDigest); - hasher->destroy(hasher); - this->attributes->set_attribute(this->attributes, - OID_PKCS9_CONTENT_TYPE, ASN1_pkcs7_data_oid); - this->attributes->set_messageDigest(this->attributes, - messageDigest); - this->attributes->set_attribute(this->attributes, - OID_PKCS9_SIGNING_TIME, signingTime); - attributes = this->attributes->get_encoding(this->attributes); - - free(messageDigest.ptr); - free(signingTime.ptr); - - private_key->build_emsa_pkcs1_signature(private_key, alg, - attributes, &encryptedDigest); - authenticatedAttributes = chunk_clone(attributes); - *authenticatedAttributes.ptr = ASN1_CONTEXT_C_0; - } - } - else if (this->data.ptr != NULL) - { - private_key->build_emsa_pkcs1_signature(private_key, alg, - this->data, &encryptedDigest); - } - if (encryptedDigest.ptr) - { - encryptedDigest = asn1_wrap(ASN1_OCTET_STRING, "m", encryptedDigest); - } - - signerInfo = asn1_wrap(ASN1_SEQUENCE, "cmcmcm", - ASN1_INTEGER_1, - pkcs7_build_issuerAndSerialNumber(cert), - asn1_algorithmIdentifier(signature_oid), - authenticatedAttributes, - asn1_algorithmIdentifier(OID_RSA_ENCRYPTION), - encryptedDigest); - - if (this->data.ptr != NULL) - { - this->content = asn1_simple_object(ASN1_OCTET_STRING, this->data); - chunk_free(&this->data); - } - this->type = OID_PKCS7_DATA; - this->data = get_contentInfo(this); - chunk_free(&this->content); - - this->type = OID_PKCS7_SIGNED_DATA; - - this->content = asn1_wrap(ASN1_SEQUENCE, "cmcmm", - ASN1_INTEGER_1, - asn1_simple_object(ASN1_SET, asn1_algorithmIdentifier(signature_oid)), - this->data, - asn1_simple_object(ASN1_CONTEXT_C_0, cert->get_certificate(cert)), - asn1_wrap(ASN1_SET, "m", signerInfo)); - - return TRUE; -} - -/** - * Implements pkcs7_t.destroy - */ -static void destroy(private_pkcs7_t *this) -{ - DESTROY_IF(this->attributes); - this->certs->destroy_offset(this->certs, offsetof(x509_t, destroy)); - free(this->content.ptr); - free(this->data.ptr); - free(this); -} - -/** - * Parse PKCS#7 contentInfo object - */ -static bool parse_contentInfo(chunk_t blob, u_int level0, private_pkcs7_t *cInfo) -{ - asn1_ctx_t ctx; - chunk_t object; - u_int level; - int objectID = 0; - - asn1_init(&ctx, blob, level0, FALSE, FALSE); - - while (objectID < PKCS7_INFO_ROOF) - { - if (!extract_object(contentInfoObjects, &objectID, &object, &level, &ctx)) - { - return FALSE; - } - - if (objectID == PKCS7_INFO_TYPE) - { - cInfo->type = known_oid(object); - if (cInfo->type < OID_PKCS7_DATA - || cInfo->type > OID_PKCS7_ENCRYPTED_DATA) - { - DBG1("unknown pkcs7 content type"); - return FALSE; - } - } - else if (objectID == PKCS7_INFO_CONTENT && object.len > 0) - { - cInfo->content = chunk_clone(object); - } - objectID++; - } - return TRUE; -} - -/** - * Generic private constructor - */ -static private_pkcs7_t *pkcs7_create_empty(void) -{ - private_pkcs7_t *this = malloc_thing(private_pkcs7_t); - - /* initialize */ - this->type = OID_UNKNOWN; - this->content = chunk_empty; - this->parsed = FALSE; - this->level = 0; - this->data = chunk_empty; - this->attributes = NULL; - this->certs = linked_list_create(); - - /*public functions */ - this->public.is_data = (bool (*) (pkcs7_t*))is_data; - this->public.is_signedData = (bool (*) (pkcs7_t*))is_signedData; - this->public.is_envelopedData = (bool (*) (pkcs7_t*))is_envelopedData; - this->public.parse_data = (bool (*) (pkcs7_t*))parse_data; - this->public.parse_signedData = (bool (*) (pkcs7_t*,x509_t*))parse_signedData; - this->public.parse_envelopedData = (bool (*) (pkcs7_t*,chunk_t,rsa_private_key_t*))parse_envelopedData; - this->public.get_data = (chunk_t (*) (pkcs7_t*))get_data; - this->public.get_contentInfo = (chunk_t (*) (pkcs7_t*))get_contentInfo; - this->public.create_certificate_iterator = (iterator_t* (*) (pkcs7_t*))create_certificate_iterator; - this->public.set_certificate = (void (*) (pkcs7_t*,x509_t*))set_certificate; - this->public.set_attributes = (void (*) (pkcs7_t*,pkcs9_t*))set_attributes; - this->public.build_envelopedData = (bool (*) (pkcs7_t*,x509_t*,encryption_algorithm_t))build_envelopedData; - this->public.build_signedData = (bool (*) (pkcs7_t*,rsa_private_key_t*,hash_algorithm_t))build_signedData; - this->public.destroy = (void (*) (pkcs7_t*))destroy; - - return this; -} - -/* - * Described in header. - */ -pkcs7_t *pkcs7_create_from_chunk(chunk_t chunk, u_int level) -{ - private_pkcs7_t *this = pkcs7_create_empty(); - - this->level = level + 2; - if (!parse_contentInfo(chunk, level, this)) - { - destroy(this); - return NULL; - } - return &this->public; -} - -/* - * Described in header. - */ -pkcs7_t *pkcs7_create_from_data(chunk_t data) -{ - private_pkcs7_t *this = pkcs7_create_empty(); - - this->data = chunk_clone(data); - this->parsed = TRUE; - - return &this->public; -} - -/* - * Described in header. - */ -pkcs7_t *pkcs7_create_from_file(const char *filename, const char *label) -{ - bool pgp = FALSE; - chunk_t chunk = chunk_empty; - char cert_label[BUF_LEN]; - pkcs7_t *pkcs7; - - snprintf(cert_label, BUF_LEN, "%s pkcs7", label); - - if (!pem_asn1_load_file(filename, NULL, cert_label, &chunk, &pgp)) - { - return NULL; - } - - pkcs7 = pkcs7_create_from_chunk(chunk, 0); - free(chunk.ptr); - return pkcs7; -} diff --git a/src/libstrongswan/crypto/pkcs7.h b/src/libstrongswan/crypto/pkcs7.h deleted file mode 100644 index 74bd25361..000000000 --- a/src/libstrongswan/crypto/pkcs7.h +++ /dev/null @@ -1,209 +0,0 @@ -/** - * @file pkcs7.h - * - * @brief Interface of pkcs7_t. - * - */ - -/* - * Copyright (C) 2005 Jan Hutter, Martin Willi - * Copyright (C) 2002-2008 Andreas Steffen - * - * Hochschule fuer Technik Rapperswil, Switzerland - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * RCSID $Id: pkcs7.h 3437 2008-02-01 22:26:01Z andreas $ - */ - -#ifndef _PKCS7_H -#define _PKCS7_H - -typedef struct pkcs7_t pkcs7_t; - -#include <library.h> -#include <crypto/x509.h> -#include <crypto/pkcs9.h> -#include <crypto/rsa/rsa_private_key.h> -#include <crypto/crypters/crypter.h> -#include <utils/iterator.h> - -/** - * @brief PKCS#7 contentInfo object. - * - * @b Constructors: - * -pkcs7_create_from_chunk() - * -pkcs7_create_from_data() - * - * @ingroup crypto - */ -struct pkcs7_t { - /** - * @brief Check if the PKCS#7 contentType is data - * - * @param this calling object - * @return TRUE if the contentType is data - */ - bool (*is_data) (pkcs7_t *this); - - /** - * @brief Check if the PKCS#7 contentType is signedData - * - * @param this calling object - * @return TRUE if the contentType is signedData - */ - bool (*is_signedData) (pkcs7_t *this); - - /** - * @brief Check if the PKCS#7 contentType is envelopedData - * - * @param this calling object - * @return TRUE if the contentType is envelopedData - */ - bool (*is_envelopedData) (pkcs7_t *this); - - /** - * @brief Parse a PKCS#7 data content. - * - * @param this calling object - * @return TRUE if parsing was successful - */ - bool (*parse_data) (pkcs7_t *this); - - /** - * @brief Parse a PKCS#7 signedData content. - * - * @param this calling object - * @param cacert cacert used to verify the signature - * @return TRUE if parsing was successful - */ - bool (*parse_signedData) (pkcs7_t *this, x509_t *cacert); - - /** - * @brief Parse a PKCS#7 envelopedData content. - * - * @param this calling object - * @param serialNumber serialNumber of the request - * @param key RSA private key used to decrypt the symmetric key - * @return TRUE if parsing was successful - */ - bool (*parse_envelopedData) (pkcs7_t *this, chunk_t serialNumber, rsa_private_key_t *key); - - /** - * @brief Returns the parsed data object - * - * @param this calling object - * @return chunk containing the data object - */ - chunk_t (*get_data) (pkcs7_t *this); - - /** - * @brief Returns the a DER-encoded contentInfo object - * - * @param this calling object - * @return chunk containing the contentInfo object - */ - chunk_t (*get_contentInfo) (pkcs7_t *this); - - /** - * @brief Create an iterator for the certificates. - * - * @param this calling object - * @return iterator for the certificates - */ - iterator_t *(*create_certificate_iterator) (pkcs7_t *this); - - /** - * @brief Add a certificate. - * - * @param this calling object - * @param cert certificate to be included - */ - void (*set_certificate) (pkcs7_t *this, x509_t *cert); - - /** - * @brief Add authenticated attributes. - * - * @param this calling object - * @param attributes attributes to be included - */ - void (*set_attributes) (pkcs7_t *this, pkcs9_t *attributes); - - /** - * @brief Build a data object - * - * @param this PKCS#7 data to be built - * @return TRUE if build was successful - */ - bool (*build_data) (pkcs7_t *this); - - /** - * @brief Build an envelopedData object - * - * @param this PKCS#7 data object to envelop - * @param cert receivers's certificate - * @param alg encryption algorithm - * @return TRUE if build was successful - */ - bool (*build_envelopedData) (pkcs7_t *this, x509_t *cert, encryption_algorithm_t alg); - - /** - * @brief Build an signedData object - * - * @param this PKCS#7 data object to sign - * @param key signer's RSA private key - * @param alg digest algorithm used for signature - * @return TRUE if build was successful - */ - bool (*build_signedData) (pkcs7_t *this, rsa_private_key_t *key, hash_algorithm_t alg); - - /** - * @brief Destroys the contentInfo object. - * - * @param this PKCS#7 contentInfo object to destroy - */ - void (*destroy) (pkcs7_t *this); -}; - -/** - * @brief Read a PKCS#7 contentInfo object from a DER encoded chunk. - * - * @param chunk chunk containing DER encoded data - * @param level ASN.1 parsing start level - * @return created pkcs7_contentInfo object, or NULL if invalid. - * - * @ingroup crypto - */ -pkcs7_t *pkcs7_create_from_chunk(chunk_t chunk, u_int level); - -/** - * @brief Create a PKCS#7 contentInfo object - * - * @param chunk chunk containing data - * @return created pkcs7_contentInfo object. - * - * @ingroup crypto - */ -pkcs7_t *pkcs7_create_from_data(chunk_t data); - -/** - * @brief Read a X.509 certificate from a DER encoded file. - * - * @param filename file containing DER encoded data - * @param label label describing kind of PKCS#7 file - * @return created pkcs7_t object, or NULL if invalid. - * - * @ingroup crypto - */ -pkcs7_t *pkcs7_create_from_file(const char *filename, const char *label); - - -#endif /* _PKCS7_H */ diff --git a/src/libstrongswan/crypto/pkcs9.c b/src/libstrongswan/crypto/pkcs9.c index 1003c9011..1c1b5a586 100644 --- a/src/libstrongswan/crypto/pkcs9.c +++ b/src/libstrongswan/crypto/pkcs9.c @@ -1,13 +1,5 @@ -/** - * @file pkcs9.c - * - * @brief Implementation of pkcs9_t. - * - */ - /* * Copyright (C)2008 Andreas Steffen - * * Hochschule fuer Technik Rapperswil, Switzerland * * This program is free software; you can redistribute it and/or modify it @@ -20,7 +12,7 @@ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * - * RCSID $Id: pkcs7.c 3423 2008-01-22 10:32:37Z andreas $ + * $Id: pkcs9.c 3891 2008-04-28 16:00:52Z andreas $ */ #include <library.h> @@ -28,6 +20,7 @@ #include <asn1/oid.h> #include <asn1/asn1.h> +#include <asn1/asn1_parser.h> #include <utils/linked_list.h> #include "pkcs9.h" @@ -84,22 +77,6 @@ struct attribute_t { }; -/* ASN.1 definition of the X.501 atttribute type */ - -static const asn1Object_t attributesObjects[] = { - { 0, "attributes", ASN1_SET, ASN1_LOOP }, /* 0 */ - { 1, "attribute", ASN1_SEQUENCE, ASN1_NONE }, /* 1 */ - { 2, "type", ASN1_OID, ASN1_BODY }, /* 2 */ - { 2, "values", ASN1_SET, ASN1_LOOP }, /* 3 */ - { 3, "value", ASN1_EOC, ASN1_RAW }, /* 4 */ - { 2, "end loop", ASN1_EOC, ASN1_END }, /* 5 */ - { 0, "end loop", ASN1_EOC, ASN1_END }, /* 6 */ -}; - -#define ATTRIBUTE_OBJ_TYPE 2 -#define ATTRIBUTE_OBJ_VALUE 4 -#define ATTRIBUTE_OBJ_ROOF 7 - /** * PKCS#9 attribute type OIDs */ @@ -267,7 +244,7 @@ static void build_encoding(private_pkcs9_t *this) /* allocate memory for the attributes and build the encoding */ { - u_char *pos = build_asn1_object(&this->encoding, ASN1_SET, attributes_len); + u_char *pos = asn1_build_object(&this->encoding, ASN1_SET, attributes_len); iterator = this->attributes->create_iterator(this->attributes, TRUE); @@ -335,7 +312,8 @@ static chunk_t get_messageDigest(private_pkcs9_t *this) { return chunk_empty; } - if (!parse_asn1_simple_object(&value, asn1_attributeType(oid), 0, oid_names[oid].name)) + if (!asn1_parse_simple_object(&value, asn1_attributeType(oid), 0, + oid_names[oid].name)) { return chunk_empty; } @@ -398,29 +376,41 @@ pkcs9_t *pkcs9_create(void) } /** + * ASN.1 definition of the X.501 atttribute type + */ +static const asn1Object_t attributesObjects[] = { + { 0, "attributes", ASN1_SET, ASN1_LOOP }, /* 0 */ + { 1, "attribute", ASN1_SEQUENCE, ASN1_NONE }, /* 1 */ + { 2, "type", ASN1_OID, ASN1_BODY }, /* 2 */ + { 2, "values", ASN1_SET, ASN1_LOOP }, /* 3 */ + { 3, "value", ASN1_EOC, ASN1_RAW }, /* 4 */ + { 2, "end loop", ASN1_EOC, ASN1_END }, /* 5 */ + { 0, "end loop", ASN1_EOC, ASN1_END }, /* 6 */ + { 0, "exit", ASN1_EOC, ASN1_EXIT } +}; +#define ATTRIBUTE_OBJ_TYPE 2 +#define ATTRIBUTE_OBJ_VALUE 4 + +/** * Parse a PKCS#9 attribute list */ static bool parse_attributes(chunk_t chunk, int level0, private_pkcs9_t* this) { - asn1_ctx_t ctx; + asn1_parser_t *parser; chunk_t object; - u_int level; + int objectID; int oid = OID_UNKNOWN; - int objectID = 0; + bool success = FALSE; - asn1_init(&ctx, chunk, level0, FALSE, FALSE); + parser = asn1_parser_create(attributesObjects, chunk); + parser->set_top_level(parser, level0); - while (objectID < ATTRIBUTE_OBJ_ROOF) + while (parser->iterate(parser, &objectID, &object)) { - if (!extract_object(attributesObjects, &objectID, &object, &level, &ctx)) - { - return FALSE; - } - switch (objectID) { case ATTRIBUTE_OBJ_TYPE: - oid = known_oid(object); + oid = asn1_known_oid(object); break; case ATTRIBUTE_OBJ_VALUE: if (oid == OID_UNKNOWN) @@ -431,7 +421,8 @@ static bool parse_attributes(chunk_t chunk, int level0, private_pkcs9_t* this) { attribute_t *attribute = attribute_create(oid, object); - this->attributes->insert_last(this->attributes, (void*)attribute); + this->attributes->insert_last(this->attributes, + (void*)attribute); } /* parse known attributes */ { @@ -439,16 +430,21 @@ static bool parse_attributes(chunk_t chunk, int level0, private_pkcs9_t* this) if (type != ASN1_EOC) { - if (!parse_asn1_simple_object(&object, type, level+1, oid_names[oid].name)) + if (!asn1_parse_simple_object(&object, type, + parser->get_level(parser)+1, + oid_names[oid].name)) { - return FALSE; + goto end; } } } } - objectID++; } - return TRUE; + success = parser->success(parser); + +end: + parser->destroy(parser); + return success; } diff --git a/src/libstrongswan/crypto/pkcs9.h b/src/libstrongswan/crypto/pkcs9.h index 44915720c..89cdec83d 100644 --- a/src/libstrongswan/crypto/pkcs9.h +++ b/src/libstrongswan/crypto/pkcs9.h @@ -1,13 +1,5 @@ -/** - * @file pkcs7.h - * - * @brief Interface of pkcs9_t. - * - */ - /* - * Copyright (C) 2008 Andreas Steffen - * + * Copyright (C) 2008 Andreas Steffen * Hochschule fuer Technik Rapperswil, Switzerland * * This program is free software; you can redistribute it and/or modify it @@ -20,102 +12,89 @@ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * - * RCSID $Id: pkcs7.h 3423 2008-01-22 10:32:37Z andreas $ + * $Id: pkcs9.h 3589 2008-03-13 14:14:44Z martin $ + */ + +/** + * @defgroup pkcs9 pkcs9 + * @{ @ingroup crypto */ -#ifndef _PKCS9_H -#define _PKCS9_H +#ifndef PKCS9_H_ +#define PKCS9_H_ typedef struct pkcs9_t pkcs9_t; #include <library.h> /** - * @brief PKCS#9 . - * - * @b Constructors: - * -pkcs9_create_from_chunk() - * -pkcs9_create() - * - * @ingroup crypto + * PKCS#9 attributes. */ struct pkcs9_t { + /** - * @brief generate ASN.1 encoding of attribute list - * - * @param this PKCS#9 attribute list to be encoded + * Generate ASN.1 encoding of attribute list */ void (*build_encoding) (pkcs9_t *this); /** - * @brief gets ASN.1 encoding of PKCS#9 attribute list + * Gets ASN.1 encoding of PKCS#9 attribute list * - * @param this calling object * @return ASN.1 encoded PKCSI#9 list */ chunk_t (*get_encoding) (pkcs9_t *this); /** - * @brief gets a PKCS#9 attribute + * Gets a PKCS#9 attribute * - * @param this calling object * @param oid OID of the attribute * @return ASN.1 encoded value of the attribute */ chunk_t (*get_attribute) (pkcs9_t *this, int oid); /** - * @brief adds a PKCS#9 attribute + * Adds a PKCS#9 attribute * - * @param this calling object * @param oid OID of the attribute * @param value ASN.1 encoded value of the attribute */ void (*set_attribute) (pkcs9_t *this, int oid, chunk_t value); /** - * @brief gets a PKCS#9 messageDigest attribute + * Gets a PKCS#9 messageDigest attribute * - * @param this calling object * @return messageDigest */ chunk_t (*get_messageDigest) (pkcs9_t *this); /** - * @brief add a PKCS#9 messageDigest attribute + * Add a PKCS#9 messageDigest attribute * - * @param this calling object * @param value messageDigest */ void (*set_messageDigest) (pkcs9_t *this, chunk_t value); /** - * @brief Destroys the PKCS#9 attribute list. - * - * @param this PKCS#9 attribute list to destroy + * Destroys the PKCS#9 attribute list. */ void (*destroy) (pkcs9_t *this); }; /** - * @brief Read a PKCS#9 attribute list from a DER encoded chunk. + * Read a PKCS#9 attribute list from a DER encoded chunk. * * @param chunk chunk containing DER encoded data * @param level ASN.1 parsing start level * @return created pkcs9 attribute list, or NULL if invalid. - * - * @ingroup crypto */ pkcs9_t *pkcs9_create_from_chunk(chunk_t chunk, u_int level); /** - * @brief Create an empty PKCS#9 attribute list + * Create an empty PKCS#9 attribute list * * @param chunk chunk containing data * @return created pkcs9 attribute list. - * - * @ingroup crypto */ pkcs9_t *pkcs9_create(void); -#endif /* _PKCS9_H */ +#endif /* PKCS9_H_ @} */ diff --git a/src/libstrongswan/crypto/prf_plus.c b/src/libstrongswan/crypto/prf_plus.c index 6bd444b1f..de7dbff84 100644 --- a/src/libstrongswan/crypto/prf_plus.c +++ b/src/libstrongswan/crypto/prf_plus.c @@ -1,10 +1,3 @@ -/** - * @file prf_plus.c - * - * @brief Implementation of prf_plus_t. - * - */ - /* * Copyright (C) 2005-2006 Martin Willi * Copyright (C) 2005 Jan Hutter @@ -19,6 +12,8 @@ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. + * + * $Id: prf_plus.c 3589 2008-03-13 14:14:44Z martin $ */ #include <string.h> diff --git a/src/libstrongswan/crypto/prf_plus.h b/src/libstrongswan/crypto/prf_plus.h index 90f9ce2eb..e63827858 100644 --- a/src/libstrongswan/crypto/prf_plus.h +++ b/src/libstrongswan/crypto/prf_plus.h @@ -1,10 +1,3 @@ -/** - * @file prf_plus.h - * - * @brief Interface for prf_plus.h. - * - */ - /* * Copyright (C) 2005-2006 Martin Willi * Copyright (C) 2005 Jan Hutter @@ -19,6 +12,13 @@ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. + * + * $Id: prf_plus.h 3589 2008-03-13 14:14:44Z martin $ + */ + +/** + * @defgroup prf_plus prf_plus + * @{ @ingroup crypto */ #ifndef PRF_PLUS_H_ @@ -29,53 +29,43 @@ typedef struct prf_plus_t prf_plus_t; #include <crypto/prfs/prf.h> /** - * @brief Implementation of the prf+ function described in IKEv2 RFC. + * Implementation of the prf+ function described in IKEv2 RFC. * * This class implements the prf+ algorithm. Internally it uses a pseudo random * function, which implements the prf_t interface. - * * See IKEv2 RFC 2.13. - * - * @b Constructors: - * - prf_plus_create() - * - * @ingroup transforms */ struct prf_plus_t { /** - * @brief Get pseudo random bytes. + * Get pseudo random bytes. * * Get the next few bytes of the prf+ output. Space * must be allocated by the caller. * - * @param this calling object - * @param length number of bytes to get - * @param[out] buffer pointer where the generated bytes will be written + * @param length number of bytes to get + * @param buffer pointer where the generated bytes will be written */ void (*get_bytes) (prf_plus_t *this, size_t length, u_int8_t *buffer); /** - * @brief Allocate pseudo random bytes. + * Allocate pseudo random bytes. * * Get the next few bytes of the prf+ output. This function * will allocate the required space. * - * @param this calling object - * @param length number of bytes to get - * @param[out] chunk chunk which will hold generated bytes + * @param length number of bytes to get + * @param chunk chunk which will hold generated bytes */ void (*allocate_bytes) (prf_plus_t *this, size_t length, chunk_t *chunk); /** - * @brief Destroys a prf_plus_t object. - * - * @param this calling object + * Destroys a prf_plus_t object. */ void (*destroy) (prf_plus_t *this); }; /** - * @brief Creates a new prf_plus_t object. + * Creates a new prf_plus_t object. * * Seed will be cloned. prf will * not be cloned, must be destroyed outside after @@ -84,9 +74,7 @@ struct prf_plus_t { * @param prf prf object to use * @param seed input seed for prf * @return prf_plus_t object - * - * @ingroup transforms */ prf_plus_t *prf_plus_create(prf_t *prf, chunk_t seed); -#endif /*PRF_PLUS_H_*/ +#endif /*PRF_PLUS_H_ @} */ diff --git a/src/libstrongswan/crypto/prfs/fips_prf.c b/src/libstrongswan/crypto/prfs/fips_prf.c deleted file mode 100644 index 0ab80b089..000000000 --- a/src/libstrongswan/crypto/prfs/fips_prf.c +++ /dev/null @@ -1,258 +0,0 @@ -/** - * @file fips_prf.c - * - * @brief Implementation for fips_prf_t. - * - */ - -/* - * Copyright (C) 2006 Martin Willi - * Hochschule fuer Technik Rapperswil - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -#include "fips_prf.h" - -#include <arpa/inet.h> - -#include <debug.h> - -typedef struct private_fips_prf_t private_fips_prf_t; - -/** - * Private data of a fips_prf_t object. - */ -struct private_fips_prf_t { - /** - * Public fips_prf_t interface. - */ - fips_prf_t public; - - /** - * key of prf function, "b" long - */ - u_int8_t *key; - - /** - * size of "b" in bytes - */ - size_t b; - - /** - * G function, either SHA1 or DES - */ - void (*g)(u_int8_t t[], chunk_t c, u_int8_t res[]); -}; - -/** - * t used in G(), equals to initial SHA1 value - */ -static u_int8_t t[] = { - 0x67,0x45,0x23,0x01,0xEF,0xCD,0xAB,0x89,0x98,0xBA, - 0xDC,0xFE,0x10,0x32,0x54,0x76,0xC3,0xD2,0xE1,0xF0, -}; - -/** - * sum = (a + b) mod 2 ^ (length * 8) - */ -static void add_mod(size_t length, u_int8_t a[], u_int8_t b[], u_int8_t sum[]) -{ - int i, c = 0; - - for(i = length - 1; i >= 0; i--) - { - u_int32_t tmp; - - tmp = a[i] + b[i] + c; - sum[i] = 0xff & tmp; - c = tmp >> 8; - } -} - -/** - * calculate "chunk mod 2^(length*8)" and save it into buffer - */ -static void chunk_mod(size_t length, chunk_t chunk, u_int8_t buffer[]) -{ - if (chunk.len < length) - { - /* apply seed as least significant bits, others are zero */ - memset(buffer, 0, length - chunk.len); - memcpy(buffer + length - chunk.len, chunk.ptr, chunk.len); - } - else - { - /* use least significant bytes from seed, as we use mod 2^b */ - memcpy(buffer, chunk.ptr + chunk.len - length, length); - } -} - -/** - * Implementation of prf_t.get_bytes. - * - * Test vector: - * - * key: - * 0xbd, 0x02, 0x9b, 0xbe, 0x7f, 0x51, 0x96, 0x0b, - * 0xcf, 0x9e, 0xdb, 0x2b, 0x61, 0xf0, 0x6f, 0x0f, - * 0xeb, 0x5a, 0x38, 0xb6 - * - * seed: - * 0x00 - * - * result: - * 0x20, 0x70, 0xb3, 0x22, 0x3d, 0xba, 0x37, 0x2f, - * 0xde, 0x1c, 0x0f, 0xfc, 0x7b, 0x2e, 0x3b, 0x49, - * 0x8b, 0x26, 0x06, 0x14, 0x3c, 0x6c, 0x18, 0xba, - * 0xcb, 0x0f, 0x6c, 0x55, 0xba, 0xbb, 0x13, 0x78, - * 0x8e, 0x20, 0xd7, 0x37, 0xa3, 0x27, 0x51, 0x16 - */ -static void get_bytes(private_fips_prf_t *this, chunk_t seed, u_int8_t w[]) -{ - int i; - u_int8_t xval[this->b]; - u_int8_t xseed[this->b]; - u_int8_t sum[this->b]; - u_int8_t *xkey = this->key; - u_int8_t one[this->b]; - chunk_t xval_chunk = chunk_from_buf(xval); - - memset(one, 0, this->b); - one[this->b - 1] = 0x01; - - /* 3.1 */ - chunk_mod(this->b, seed, xseed); - - /* 3.2 */ - for (i = 0; i < 2; i++) /* twice */ - { - /* a. XVAL = (XKEY + XSEED j) mod 2^b */ - add_mod(this->b, xkey, xseed, xval); - DBG3("XVAL %b", xval, this->b); - /* b. wi = G(t, XVAL ) */ - this->g(t, xval_chunk, &w[i * this->b]); - DBG3("w[%d] %b", i, &w[i * this->b], this->b); - /* c. XKEY = (1 + XKEY + wi) mod 2b */ - add_mod(this->b, xkey, &w[i * this->b], sum); - add_mod(this->b, sum, one, xkey); - DBG3("XKEY %b", xkey, this->b); - } - - /* 3.3 done already, mod q not used */ -} - -/** - * Implementation of prf_t.get_block_size. - */ -static size_t get_block_size(private_fips_prf_t *this) -{ - return 2 * this->b; -} -/** - * Implementation of prf_t.allocate_bytes. - */ -static void allocate_bytes(private_fips_prf_t *this, chunk_t seed, chunk_t *chunk) -{ - *chunk = chunk_alloc(get_block_size(this)); - get_bytes(this, seed, chunk->ptr); -} - -/** - * Implementation of prf_t.get_key_size. - */ -static size_t get_key_size(private_fips_prf_t *this) -{ - return this->b; -} - -/** - * Implementation of prf_t.set_key. - */ -static void set_key(private_fips_prf_t *this, chunk_t key) -{ - /* save key as "key mod 2^b" */ - chunk_mod(this->b, key, this->key); -} - -/** - * Implementation of the G() function based on SHA1 - */ -void g_sha1(u_int8_t t[], chunk_t c, u_int8_t res[]) -{ - hasher_t *hasher; - u_int8_t buf[64]; - chunk_t state_chunk; - u_int32_t *state, *iv, *hash; - - if (c.len < sizeof(buf)) - { - /* pad c with zeros */ - memset(buf, 0, sizeof(buf)); - memcpy(buf, c.ptr, c.len); - c.ptr = buf; - c.len = sizeof(buf); - } - else - { - /* not more than 512 bits can be G()-ed */ - c.len = sizeof(buf); - } - - /* our SHA1 hasher's state is 32-Bit integers in host order. We must - * convert them */ - hasher = hasher_create(HASH_SHA1); - state_chunk = hasher->get_state(hasher); - state = (u_int32_t*)state_chunk.ptr; - iv = (u_int32_t*)t; - hash = (u_int32_t*)res; - state[0] = htonl(iv[0]); - state[1] = htonl(iv[1]); - state[2] = htonl(iv[2]); - state[3] = htonl(iv[3]); - hasher->get_hash(hasher, c, NULL); - hash[0] = htonl(state[0]); - hash[1] = htonl(state[1]); - hash[2] = htonl(state[2]); - hash[3] = htonl(state[3]); - hash[4] = htonl(state[4]); - hasher->destroy(hasher); -} - -/** - * Implementation of prf_t.destroy. - */ -static void destroy(private_fips_prf_t *this) -{ - free(this->key); - free(this); -} - -/* - * Described in header. - */ -fips_prf_t *fips_prf_create(size_t b, void(*g)(u_int8_t[],chunk_t,u_int8_t[])) -{ - private_fips_prf_t *this = malloc_thing(private_fips_prf_t); - - this->public.prf_interface.get_bytes = (void (*) (prf_t *,chunk_t,u_int8_t*))get_bytes; - this->public.prf_interface.allocate_bytes = (void (*) (prf_t*,chunk_t,chunk_t*))allocate_bytes; - this->public.prf_interface.get_block_size = (size_t (*) (prf_t*))get_block_size; - this->public.prf_interface.get_key_size = (size_t (*) (prf_t*))get_key_size; - this->public.prf_interface.set_key = (void (*) (prf_t *,chunk_t))set_key; - this->public.prf_interface.destroy = (void (*) (prf_t *))destroy; - - this->g = g; - this->b = b; - this->key = malloc(b); - - return &(this->public); -} diff --git a/src/libstrongswan/crypto/prfs/fips_prf.h b/src/libstrongswan/crypto/prfs/fips_prf.h deleted file mode 100644 index 283ee1f61..000000000 --- a/src/libstrongswan/crypto/prfs/fips_prf.h +++ /dev/null @@ -1,80 +0,0 @@ -/** - * @file fips_prf.h - * - * @brief Interface of fips_prf_t. - * - */ - -/* - * Copyright (C) 2006 Martin Willi - * Hochschule fuer Technik Rapperswil - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -#ifndef FIPS_PRF_H_ -#define FIPS_PRF_H_ - -typedef struct fips_prf_t fips_prf_t; - -#include <library.h> -#include <crypto/prfs/prf.h> -#include <crypto/hashers/hasher.h> - -/** - * @brief Implementation of prf_t using the FIPS 186-2-change1 standard. - * - * FIPS defines a "General Purpose Random Number Generator" (Revised - * Algorithm for Computing m values of x (Appendix 3.1 of FIPS 186-2)). This - * implementation is not intended for private key generation and therefore does - * not include the "mod q" operation (see FIPS 186-2-change1 p74). - * The FIPS PRF is stateful; the key changes every time when bytes are acquired. - * - * @b Constructors: - * - fips_prf_create() - * - prf_create() using one of the FIPS algorithms - * - * @ingroup prfs - */ -struct fips_prf_t { - - /** - * Generic prf_t interface for this fips_prf_t class. - */ - prf_t prf_interface; -}; - -/** - * @brief Creates a new fips_prf_t object. - * - * FIPS 186-2 defines G() functions used in the PRF function. It can - * be implemented either based on SHA1 or DES. - * - * @param b size of b (in bytes, not bits) - * @param g G() function to use (e.g. g_sha1) - * @return - * - fips_prf_t object - * - NULL if b invalid not supported - * - * @ingroup prfs - */ -fips_prf_t *fips_prf_create(size_t b, void(*g)(u_int8_t[],chunk_t,u_int8_t[])); - -/** - * @brief Implementation of the G() function based on SHA1. - * - * @param t initialization vector for SHA1 hasher, 20 bytes long - * @param c value to hash, not longer than 512 bit - * @param res result of G(), requries 20 bytes - */ -void g_sha1(u_int8_t t[], chunk_t c, u_int8_t res[]); - -#endif /* FIPS_PRF_H_ */ diff --git a/src/libstrongswan/crypto/prfs/hmac_prf.c b/src/libstrongswan/crypto/prfs/hmac_prf.c deleted file mode 100644 index f315f880d..000000000 --- a/src/libstrongswan/crypto/prfs/hmac_prf.c +++ /dev/null @@ -1,118 +0,0 @@ -/** - * @file hmac_prf.c - * - * @brief Implementation for hmac_prf_t. - * - */ - -/* - * Copyright (C) 2005-2006 Martin Willi - * Copyright (C) 2005 Jan Hutter - * Hochschule fuer Technik Rapperswil - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -#include "hmac_prf.h" - -#include <crypto/hmac.h> - - -typedef struct private_hmac_prf_t private_hmac_prf_t; - -/** - * Private data of a hma_prf_t object. - */ -struct private_hmac_prf_t { - /** - * Public hmac_prf_t interface. - */ - hmac_prf_t public; - - /** - * Hmac to use for generation. - */ - hmac_t *hmac; -}; - -/** - * Implementation of prf_t.get_bytes. - */ -static void get_bytes(private_hmac_prf_t *this, chunk_t seed, u_int8_t *buffer) -{ - this->hmac->get_mac(this->hmac, seed, buffer); -} - -/** - * Implementation of prf_t.allocate_bytes. - */ -static void allocate_bytes(private_hmac_prf_t *this, chunk_t seed, chunk_t *chunk) -{ - this->hmac->allocate_mac(this->hmac, seed, chunk); -} - -/** - * Implementation of prf_t.get_block_size. - */ -static size_t get_block_size(private_hmac_prf_t *this) -{ - return this->hmac->get_block_size(this->hmac); -} - -/** - * Implementation of prf_t.get_block_size. - */ -static size_t get_key_size(private_hmac_prf_t *this) -{ - /* for HMAC prfs, IKEv2 uses block size as key size */ - return this->hmac->get_block_size(this->hmac); -} - -/** - * Implementation of prf_t.set_key. - */ -static void set_key(private_hmac_prf_t *this, chunk_t key) -{ - this->hmac->set_key(this->hmac, key); -} - -/** - * Implementation of prf_t.destroy. - */ -static void destroy(private_hmac_prf_t *this) -{ - this->hmac->destroy(this->hmac); - free(this); -} - -/* - * Described in header. - */ -hmac_prf_t *hmac_prf_create(hash_algorithm_t hash_algorithm) -{ - private_hmac_prf_t *this = malloc_thing(private_hmac_prf_t); - - this->public.prf_interface.get_bytes = (void (*) (prf_t *,chunk_t,u_int8_t*))get_bytes; - this->public.prf_interface.allocate_bytes = (void (*) (prf_t*,chunk_t,chunk_t*))allocate_bytes; - this->public.prf_interface.get_block_size = (size_t (*) (prf_t*))get_block_size; - this->public.prf_interface.get_key_size = (size_t (*) (prf_t*))get_key_size; - this->public.prf_interface.set_key = (void (*) (prf_t *,chunk_t))set_key; - this->public.prf_interface.destroy = (void (*) (prf_t *))destroy; - - this->hmac = hmac_create(hash_algorithm); - if (this->hmac == NULL) - { - free(this); - return NULL; - } - - return &(this->public); -} diff --git a/src/libstrongswan/crypto/prfs/hmac_prf.h b/src/libstrongswan/crypto/prfs/hmac_prf.h deleted file mode 100644 index 9b06ee3a2..000000000 --- a/src/libstrongswan/crypto/prfs/hmac_prf.h +++ /dev/null @@ -1,65 +0,0 @@ -/** - * @file hmac_prf.h - * - * @brief Interface of hmac_prf_t. - * - */ - -/* - * Copyright (C) 2005-2006 Martin Willi - * Copyright (C) 2005 Jan Hutter - * Hochschule fuer Technik Rapperswil - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -#ifndef PRF_HMAC_H_ -#define PRF_HMAC_H_ - -typedef struct hmac_prf_t hmac_prf_t; - -#include <library.h> -#include <crypto/prfs/prf.h> -#include <crypto/hashers/hasher.h> - -/** - * @brief Implementation of prf_t interface using the - * HMAC algorithm. - * - * This simply wraps a hmac_t in a prf_t. More a question of - * interface matching. - * - * @b Constructors: - * - hmac_prf_create() - * - * @ingroup prfs - */ -struct hmac_prf_t { - - /** - * Generic prf_t interface for this hmac_prf_t class. - */ - prf_t prf_interface; -}; - -/** - * @brief Creates a new hmac_prf_t object. - * - * @param hash_algorithm hmac's hash algorithm - * @return - * - hmac_prf_t object - * - NULL if hash not supported - * - * @ingroup prfs - */ -hmac_prf_t *hmac_prf_create(hash_algorithm_t hash_algorithm); - -#endif /*PRF_HMAC_SHA1_H_*/ diff --git a/src/libstrongswan/crypto/prfs/prf.c b/src/libstrongswan/crypto/prfs/prf.c index f803829af..812f6278d 100644 --- a/src/libstrongswan/crypto/prfs/prf.c +++ b/src/libstrongswan/crypto/prfs/prf.c @@ -1,10 +1,3 @@ -/** - * @file prf.c - * - * @brief Generic constructor for all prf_t - * - */ - /* * Copyright (C) 2005-2006 Martin Willi * Copyright (C) 2005 Jan Hutter @@ -19,20 +12,18 @@ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. + * + * $Id: prf.c 3619 2008-03-19 14:02:52Z martin $ */ - #include "prf.h" -#include <crypto/hashers/hasher.h> -#include <crypto/prfs/hmac_prf.h> -#include <crypto/prfs/fips_prf.h> - -ENUM_BEGIN(pseudo_random_function_names, PRF_UNDEFINED, PRF_FIPS_DES, +ENUM_BEGIN(pseudo_random_function_names, PRF_UNDEFINED, PRF_KEYED_SHA1, "PRF_UNDEFINED", "PRF_FIPS_SHA1_160", - "PRF_FIPS_DES"); -ENUM_NEXT(pseudo_random_function_names, PRF_HMAC_MD5, PRF_HMAC_SHA2_512, PRF_FIPS_DES, + "PRF_FIPS_DES", + "PRF_KEYED_SHA1"); +ENUM_NEXT(pseudo_random_function_names, PRF_HMAC_MD5, PRF_HMAC_SHA2_512, PRF_KEYED_SHA1, "PRF_HMAC_MD5", "PRF_HMAC_SHA1", "PRF_HMAC_TIGER", @@ -42,29 +33,3 @@ ENUM_NEXT(pseudo_random_function_names, PRF_HMAC_MD5, PRF_HMAC_SHA2_512, PRF_FIP "PRF_HMAC_SHA2_512"); ENUM_END(pseudo_random_function_names, PRF_HMAC_SHA2_512); -/* - * Described in header. - */ -prf_t *prf_create(pseudo_random_function_t pseudo_random_function) -{ - switch (pseudo_random_function) - { - case PRF_HMAC_SHA1: - return (prf_t*)hmac_prf_create(HASH_SHA1); - case PRF_HMAC_MD5: - return (prf_t*)hmac_prf_create(HASH_MD5); - case PRF_HMAC_SHA2_256: - return (prf_t*)hmac_prf_create(HASH_SHA256); - case PRF_HMAC_SHA2_384: - return (prf_t*)hmac_prf_create(HASH_SHA384); - case PRF_HMAC_SHA2_512: - return (prf_t*)hmac_prf_create(HASH_SHA512); - case PRF_FIPS_SHA1_160: - return (prf_t*)fips_prf_create(20, g_sha1); - case PRF_FIPS_DES: - case PRF_HMAC_TIGER: - case PRF_AES128_CBC: - default: - return NULL; - } -} diff --git a/src/libstrongswan/crypto/prfs/prf.h b/src/libstrongswan/crypto/prfs/prf.h index 8560a4a9c..324eb89b4 100644 --- a/src/libstrongswan/crypto/prfs/prf.h +++ b/src/libstrongswan/crypto/prfs/prf.h @@ -1,10 +1,3 @@ -/** - * @file prf.h - * - * @brief Interface prf_t. - * - */ - /* * Copyright (C) 2005-2006 Martin Willi * Copyright (C) 2005 Jan Hutter @@ -19,6 +12,13 @@ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. + * + * $Id: prf.h 3916 2008-05-08 12:43:27Z martin $ + */ + +/** + * @defgroup prf prf + * @{ @ingroup crypto */ #ifndef PRF_H_ @@ -30,12 +30,10 @@ typedef struct prf_t prf_t; #include <library.h> /** - * @brief Pseudo random function, as in IKEv2 RFC 3.3.2. + * Pseudo random function, as in IKEv2 RFC 3.3.2. * * PRF algorithms not defined in IKEv2 are allocated in "private use" * space. - * - * @ingroup prfs */ enum pseudo_random_function_t { PRF_UNDEFINED = 1024, @@ -44,7 +42,7 @@ enum pseudo_random_function_t { /** Implemented via hmac_prf_t. */ PRF_HMAC_SHA1 = 2, PRF_HMAC_TIGER = 3, - PRF_AES128_CBC = 4, + PRF_AES128_XCBC = 4, /** Implemented via hmac_prf_t. */ PRF_HMAC_SHA2_256 = 5, /** Implemented via hmac_prf_t. */ @@ -55,6 +53,11 @@ enum pseudo_random_function_t { PRF_FIPS_SHA1_160 = 1025, /** Could be implemented via fips_prf_t, uses fixed output size of 160bit */ PRF_FIPS_DES = 1026, + /** + * Keyed hash algorithm using SHA1, used in EAP-AKA: + * This PRF uses SHA1, but XORs the key into the IV. No "Final()" operation + * is applied to the SHA1 state. */ + PRF_KEYED_SHA1 = 1027, }; /** @@ -63,80 +66,53 @@ enum pseudo_random_function_t { extern enum_name_t *pseudo_random_function_names; /** - * @brief Generic interface for pseudo-random-functions. - * - * @b Constructors: - * - prf_create() - * - hmac_prf_create() - * - * @todo Implement more prf algorithms - * - * @ingroup prfs + * Generic interface for pseudo-random-functions. */ struct prf_t { /** - * @brief Generates pseudo random bytes and writes them in the buffer. + * Generates pseudo random bytes and writes them in the buffer. * - * @param this calling object - * @param seed a chunk containing the seed for the next bytes - * @param[out] buffer pointer where the generated bytes will be written + * @param seed a chunk containing the seed for the next bytes + * @param buffer pointer where the generated bytes will be written */ void (*get_bytes) (prf_t *this, chunk_t seed, u_int8_t *buffer); /** - * @brief Generates pseudo random bytes and allocate space for them. + * Generates pseudo random bytes and allocate space for them. * - * @param this calling object - * @param seed a chunk containing the seed for the next bytes - * @param[out] chunk chunk which will hold generated bytes + * @param seed a chunk containing the seed for the next bytes + * @param chunk chunk which will hold generated bytes */ void (*allocate_bytes) (prf_t *this, chunk_t seed, chunk_t *chunk); /** - * @brief Get the block size of this prf_t object. + * Get the block size of this prf_t object. * - * @param this calling object - * @return block size in bytes + * @return block size in bytes */ size_t (*get_block_size) (prf_t *this); /** - * @brief Get the key size of this prf_t object. + * Get the key size of this prf_t object. * * This is a suggestion only, all implemented PRFs accept variable key * length. * - * @param this calling object - * @return key size in bytes + * @return key size in bytes */ size_t (*get_key_size) (prf_t *this); /** - * @brief Set the key for this prf_t object. + * Set the key for this prf_t object. * - * @param this calling object - * @param key key to set + * @param key key to set */ void (*set_key) (prf_t *this, chunk_t key); /** - * @brief Destroys a prf object. - * - * @param this calling object + * Destroys a prf object. */ void (*destroy) (prf_t *this); }; -/** - * @brief Generic constructor for a prf_t oject. - * - * @param pseudo_random_function Algorithm to use - * @return - * - prf_t object - * - NULL if prf algorithm not supported - * - * @ingroup prfs - */ -prf_t *prf_create(pseudo_random_function_t pseudo_random_function); - -#endif /*PRF_H_*/ +#endif /*PRF_H_ @} */ diff --git a/src/libstrongswan/crypto/rngs/rng.c b/src/libstrongswan/crypto/rngs/rng.c new file mode 100644 index 000000000..435e043e8 --- /dev/null +++ b/src/libstrongswan/crypto/rngs/rng.c @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2008 Martin Willi + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * $Id$ + */ + +#include "rng.h" + +ENUM(rng_quality_names, RNG_WEAK, RNG_REAL, + "RNG_WEAK", + "RNG_STRONG", + "RNG_REAL", +); diff --git a/src/libstrongswan/crypto/rngs/rng.h b/src/libstrongswan/crypto/rngs/rng.h new file mode 100644 index 000000000..08f7af209 --- /dev/null +++ b/src/libstrongswan/crypto/rngs/rng.h @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2008 Martin Willi + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * $Id: rng.h 3619 2008-03-19 14:02:52Z martin $ + */ + +/** + * @defgroup rng rng + * @{ @ingroup crypto + */ + +#ifndef RNG_H_ +#define RNG_H_ + +typedef enum rng_quality_t rng_quality_t; +typedef struct rng_t rng_t; + +#include <library.h> + +/** + * Quality of generated random bytes. + */ +enum rng_quality_t { + /** weak randomness, usable for nonces, IVs */ + RNG_WEAK, + /** stronger randomness, usable for session keys */ + RNG_STRONG, + /** real random, key material */ + RNG_REAL, +}; + +/** + * enum name for rng_quality_t. + */ +extern enum_name_t *rng_quality_names; + +/** + * Generic interface for random number generators. + */ +struct rng_t { + + /** + * Generates random bytes and writes them in the buffer. + * + * @param len number of bytes to get + * @param buffer pointer where the generated bytes will be written + */ + void (*get_bytes) (rng_t *this, u_int len, u_int8_t *buffer); + + /** + * Generates random bytes and allocate space for them. + * + * @param len number of bytes to get + * @param chunk chunk which will hold generated bytes + */ + void (*allocate_bytes) (rng_t *this, u_int len, chunk_t *chunk); + + /** + * Destroys a rng object. + */ + void (*destroy) (rng_t *this); +}; + +#endif /*RNG_H_ @} */ diff --git a/src/libstrongswan/crypto/rsa/rsa_private_key.c b/src/libstrongswan/crypto/rsa/rsa_private_key.c deleted file mode 100644 index 1b1499887..000000000 --- a/src/libstrongswan/crypto/rsa/rsa_private_key.c +++ /dev/null @@ -1,722 +0,0 @@ -/** - * @file rsa_private_key.c - * - * @brief Implementation of rsa_private_key_t. - * - */ - -/* - * Copyright (C) 2005 Jan Hutter - * Copyright (C) 2005-2006 Martin Willi - * Copyright (C) 2007-2008 Andreas Steffen - * - * Hochschule fuer Technik Rapperswil - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * RCSID $Id: rsa_private_key.c 3429 2008-01-27 20:59:22Z andreas $ - */ - -#include <gmp.h> -#include <sys/stat.h> -#include <unistd.h> -#include <string.h> - -#include "rsa_public_key.h" -#include "rsa_private_key.h" - -#include <debug.h> -#include <asn1/asn1.h> -#include <asn1/pem.h> -#include <utils/randomizer.h> - -/** - * defined in rsa_public_key.c - */ -extern chunk_t rsa_public_key_info_to_asn1(const mpz_t n, const mpz_t e); -extern chunk_t rsa_public_key_id_create(const mpz_t n, const mpz_t e); - -/** - * Public exponent to use for key generation. - */ -#define PUBLIC_EXPONENT 0x10001 - -typedef struct private_rsa_private_key_t private_rsa_private_key_t; - -/** - * Private data of a rsa_private_key_t object. - */ -struct private_rsa_private_key_t { - /** - * Public interface for this signer. - */ - rsa_private_key_t public; - - /** - * Version of key, as encoded in PKCS#1 - */ - u_int version; - - /** - * Public modulus. - */ - mpz_t n; - - /** - * Public exponent. - */ - mpz_t e; - - /** - * Private prime 1. - */ - mpz_t p; - - /** - * Private Prime 2. - */ - mpz_t q; - - /** - * Private exponent. - */ - mpz_t d; - - /** - * Private exponent 1. - */ - mpz_t exp1; - - /** - * Private exponent 2. - */ - mpz_t exp2; - - /** - * Private coefficient. - */ - mpz_t coeff; - - /** - * Keysize in bytes. - */ - size_t k; - - /** - * Keyid formed as a SHA-1 hash of a publicKeyInfo object - */ - chunk_t keyid; - - /** - * @brief Implements the RSADP algorithm specified in PKCS#1. - * - * @param this calling object - * @param data data to process - * @return processed data - */ - chunk_t (*rsadp) (private_rsa_private_key_t *this, chunk_t data); - - /** - * @brief Implements the RSASP1 algorithm specified in PKCS#1. - * @param this calling object - * @param data data to process - * @return processed data - */ - chunk_t (*rsasp1) (private_rsa_private_key_t *this, chunk_t data); -}; - -/* ASN.1 definition of a PKCS#1 RSA private key */ -static const asn1Object_t privkey_objects[] = { - { 0, "RSAPrivateKey", ASN1_SEQUENCE, ASN1_NONE }, /* 0 */ - { 1, "version", ASN1_INTEGER, ASN1_BODY }, /* 1 */ - { 1, "modulus", ASN1_INTEGER, ASN1_BODY }, /* 2 */ - { 1, "publicExponent", ASN1_INTEGER, ASN1_BODY }, /* 3 */ - { 1, "privateExponent", ASN1_INTEGER, ASN1_BODY }, /* 4 */ - { 1, "prime1", ASN1_INTEGER, ASN1_BODY }, /* 5 */ - { 1, "prime2", ASN1_INTEGER, ASN1_BODY }, /* 6 */ - { 1, "exponent1", ASN1_INTEGER, ASN1_BODY }, /* 7 */ - { 1, "exponent2", ASN1_INTEGER, ASN1_BODY }, /* 8 */ - { 1, "coefficient", ASN1_INTEGER, ASN1_BODY }, /* 9 */ - { 1, "otherPrimeInfos", ASN1_SEQUENCE, ASN1_OPT | - ASN1_LOOP }, /* 10 */ - { 2, "otherPrimeInfo", ASN1_SEQUENCE, ASN1_NONE }, /* 11 */ - { 3, "prime", ASN1_INTEGER, ASN1_BODY }, /* 12 */ - { 3, "exponent", ASN1_INTEGER, ASN1_BODY }, /* 13 */ - { 3, "coefficient", ASN1_INTEGER, ASN1_BODY }, /* 14 */ - { 1, "end opt or loop", ASN1_EOC, ASN1_END } /* 15 */ -}; - -#define PRIV_KEY_VERSION 1 -#define PRIV_KEY_MODULUS 2 -#define PRIV_KEY_PUB_EXP 3 -#define PRIV_KEY_PRIV_EXP 4 -#define PRIV_KEY_PRIME1 5 -#define PRIV_KEY_PRIME2 6 -#define PRIV_KEY_EXP1 7 -#define PRIV_KEY_EXP2 8 -#define PRIV_KEY_COEFF 9 -#define PRIV_KEY_ROOF 16 - -/** - * Auxiliary function overwriting private key material with - * pseudo-random bytes before releasing it - */ -static void mpz_clear_randomized(mpz_t z) -{ - size_t len = mpz_size(z) * GMP_LIMB_BITS / BITS_PER_BYTE; - u_int8_t *random_bytes = alloca(len); - - randomizer_t *randomizer = randomizer_create(); - - randomizer->get_pseudo_random_bytes(randomizer, len, random_bytes); - - /* overwrite mpz_t with pseudo-random bytes before clearing it */ - mpz_import(z, len, 1, 1, 1, 0, random_bytes); - mpz_clear(z); - - randomizer->destroy(randomizer); -} - -/** - * Generate a random prime number with prime_len bytes - */ -static status_t compute_prime(private_rsa_private_key_t *this, size_t prime_len, mpz_t *prime) -{ - randomizer_t *randomizer; - chunk_t random_bytes; - status_t status; - - randomizer = randomizer_create(); - mpz_init(*prime); - - do - { - DBG1(" generating %d bit prime from %s ...", BITS_PER_BYTE * prime_len, DEV_RANDOM); - status = randomizer->allocate_random_bytes(randomizer, prime_len, &random_bytes); - if (status != SUCCESS) - { - randomizer->destroy(randomizer); - mpz_clear(*prime); - return FAILED; - } - - /* make sure most significant bit is set */ - random_bytes.ptr[0] = random_bytes.ptr[0] | 0x80; - - /* convert chunk to mpz value */ - mpz_import(*prime, random_bytes.len, 1, 1, 1, 0, random_bytes.ptr); - - /* get next prime */ - mpz_nextprime (*prime, *prime); - - /* free the random_bytes after overwriting them with a pseudo-random sequence */ - chunk_free_randomized(&random_bytes); - } - /* check if it isnt too large */ - while (((mpz_sizeinbase(*prime, 2) + 7) / BITS_PER_BYTE) > prime_len); - - randomizer->destroy(randomizer); - return SUCCESS; -} - -/** - * Implementation of private_rsa_private_key_t.rsadp and private_rsa_private_key_t.rsasp1. - */ -static chunk_t rsadp(private_rsa_private_key_t *this, chunk_t data) -{ - mpz_t t1, t2; - chunk_t decrypted; - - mpz_init(t1); - mpz_init(t2); - - mpz_import(t1, data.len, 1, 1, 1, 0, data.ptr); - - mpz_powm(t2, t1, this->exp1, this->p); /* m1 = c^dP mod p */ - mpz_powm(t1, t1, this->exp2, this->q); /* m2 = c^dQ mod Q */ - mpz_sub(t2, t2, t1); /* h = qInv (m1 - m2) mod p */ - mpz_mod(t2, t2, this->p); - mpz_mul(t2, t2, this->coeff); - mpz_mod(t2, t2, this->p); - - mpz_mul(t2, t2, this->q); /* m = m2 + h q */ - mpz_add(t1, t1, t2); - - decrypted.len = this->k; - decrypted.ptr = mpz_export(NULL, NULL, 1, decrypted.len, 1, 0, t1); - - mpz_clear_randomized(t1); - mpz_clear_randomized(t2); - - return decrypted; -} - -/** - * Implementation of rsa_private_key_t.pkcs1_decrypt. - */ -static status_t pkcs1_decrypt(private_rsa_private_key_t *this, - chunk_t in, chunk_t *out) -{ - status_t status = FAILED; - chunk_t em, em_ori; - - /* decrypt the input data */ - em = em_ori = this->rsadp(this, in); - - /* PKCS#1 v1.5 EME encryption formatting - * EM = 00 || 02 || PS || 00 || M - * PS = pseudo-random nonzero octets - */ - - /* check for magic bytes */ - if (*(em.ptr) != 0x00 || *(em.ptr+1) != 0x02) - { - DBG1("incorrect padding - probably wrong RSA key"); - goto end; - } - em.ptr += 2; - em.len -= 2; - - /* the plaintext data starts after first 0x00 byte */ - while (em.len-- > 0 && *em.ptr++ != 0x00); - - if (em.len == 0) - { - DBG1("no plaintext data found"); - goto end; - } - - *out = chunk_clone(em); - status = SUCCESS; - -end: - free(em_ori.ptr); - return status; -} - -/** - * Implementation of rsa_private_key_t.build_emsa_pkcs1_signature. - */ -static status_t build_emsa_pkcs1_signature(private_rsa_private_key_t *this, - hash_algorithm_t hash_algorithm, - chunk_t data, chunk_t *signature) -{ - hasher_t *hasher; - chunk_t em, digestInfo, hash; - int hash_oid = hasher_algorithm_to_oid(hash_algorithm); - - if (hash_oid == OID_UNKNOWN) - { - return NOT_SUPPORTED; - } - - /* get hasher */ - hasher = hasher_create(hash_algorithm); - if (hasher == NULL) - { - return NOT_SUPPORTED; - } - - /* build hash */ - hasher->allocate_hash(hasher, data, &hash); - hasher->destroy(hasher); - - /* build DER-encoded digestInfo */ - digestInfo = asn1_wrap(ASN1_SEQUENCE, "cm", - asn1_algorithmIdentifier(hash_oid), - asn1_simple_object(ASN1_OCTET_STRING, hash) - ); - chunk_free(&hash); - - /* build chunk to rsa-decrypt: - * EM = 0x00 || 0x01 || PS || 0x00 || T. - * PS = 0xFF padding, with length to fill em - * T = encoded_hash - */ - em.len = this->k; - em.ptr = malloc(em.len); - - /* fill em with padding */ - memset(em.ptr, 0xFF, em.len); - /* set magic bytes */ - *(em.ptr) = 0x00; - *(em.ptr+1) = 0x01; - *(em.ptr + em.len - digestInfo.len - 1) = 0x00; - /* set DER-encoded hash */ - memcpy(em.ptr + em.len - digestInfo.len, digestInfo.ptr, digestInfo.len); - - /* build signature */ - *signature = this->rsasp1(this, em); - - free(digestInfo.ptr); - free(em.ptr); - - return SUCCESS; -} - -/** - * Implementation of rsa_private_key_t.pkcs1_write. - */ -static bool pkcs1_write(private_rsa_private_key_t *this, const char *filename, bool force) -{ - bool status; - - chunk_t pkcs1 = asn1_wrap(ASN1_SEQUENCE, "cmmmmmmmm", - ASN1_INTEGER_0, - asn1_integer_from_mpz(this->n), - asn1_integer_from_mpz(this->e), - asn1_integer_from_mpz(this->d), - asn1_integer_from_mpz(this->p), - asn1_integer_from_mpz(this->q), - asn1_integer_from_mpz(this->exp1), - asn1_integer_from_mpz(this->exp2), - asn1_integer_from_mpz(this->coeff)); - - status = chunk_write(pkcs1, filename, "pkcs1", 0066, force); - chunk_free_randomized(&pkcs1); - return status; -} - -/** - * Implementation of rsa_private_key_t.get_public_key. - */ -rsa_public_key_t *get_public_key(private_rsa_private_key_t *this) -{ - return rsa_public_key_create(this->n, this->e); -} - -/** - * Implementation of rsa_private_key.belongs_to. - */ -static bool belongs_to(private_rsa_private_key_t *this, rsa_public_key_t *public) -{ - return chunk_equals(this->keyid, public->get_keyid(public)); -} - -/** - * Check the loaded key if it is valid and usable - * TODO: Log errors - */ -static status_t check(private_rsa_private_key_t *this) -{ - mpz_t t, u, q1; - status_t status = SUCCESS; - - /* PKCS#1 1.5 section 6 requires modulus to have at least 12 octets. - * We actually require more (for security). - */ - if (this->k < 512 / BITS_PER_BYTE) - { - return FAILED; - } - - /* we picked a max modulus size to simplify buffer allocation */ - if (this->k > 8192 / BITS_PER_BYTE) - { - return FAILED; - } - - mpz_init(t); - mpz_init(u); - mpz_init(q1); - - /* check that n == p * q */ - mpz_mul(u, this->p, this->q); - if (mpz_cmp(u, this->n) != 0) - { - status = FAILED; - } - - /* check that e divides neither p-1 nor q-1 */ - mpz_sub_ui(t, this->p, 1); - mpz_mod(t, t, this->e); - if (mpz_cmp_ui(t, 0) == 0) - { - status = FAILED; - } - - mpz_sub_ui(t, this->q, 1); - mpz_mod(t, t, this->e); - if (mpz_cmp_ui(t, 0) == 0) - { - status = FAILED; - } - - /* check that d is e^-1 (mod lcm(p-1, q-1)) */ - /* see PKCS#1v2, aka RFC 2437, for the "lcm" */ - mpz_sub_ui(q1, this->q, 1); - mpz_sub_ui(u, this->p, 1); - mpz_gcd(t, u, q1); /* t := gcd(p-1, q-1) */ - mpz_mul(u, u, q1); /* u := (p-1) * (q-1) */ - mpz_divexact(u, u, t); /* u := lcm(p-1, q-1) */ - - mpz_mul(t, this->d, this->e); - mpz_mod(t, t, u); - if (mpz_cmp_ui(t, 1) != 0) - { - status = FAILED; - } - - /* check that exp1 is d mod (p-1) */ - mpz_sub_ui(u, this->p, 1); - mpz_mod(t, this->d, u); - if (mpz_cmp(t, this->exp1) != 0) - { - status = FAILED; - } - - /* check that exp2 is d mod (q-1) */ - mpz_sub_ui(u, this->q, 1); - mpz_mod(t, this->d, u); - if (mpz_cmp(t, this->exp2) != 0) - { - status = FAILED; - } - - /* check that coeff is (q^-1) mod p */ - mpz_mul(t, this->coeff, this->q); - mpz_mod(t, t, this->p); - if (mpz_cmp_ui(t, 1) != 0) - { - status = FAILED; - } - - mpz_clear_randomized(t); - mpz_clear_randomized(u); - mpz_clear_randomized(q1); - return status; -} - -/** - * Implementation of rsa_private_key.destroy. - */ -static void destroy(private_rsa_private_key_t *this) -{ - mpz_clear_randomized(this->n); - mpz_clear_randomized(this->e); - mpz_clear_randomized(this->p); - mpz_clear_randomized(this->q); - mpz_clear_randomized(this->d); - mpz_clear_randomized(this->exp1); - mpz_clear_randomized(this->exp2); - mpz_clear_randomized(this->coeff); - chunk_free_randomized(&this->keyid); - free(this); -} - -/** - * Internal generic constructor - */ -static private_rsa_private_key_t *rsa_private_key_create_empty(void) -{ - private_rsa_private_key_t *this = malloc_thing(private_rsa_private_key_t); - - /* public functions */ - this->public.pkcs1_decrypt = (status_t (*) (rsa_private_key_t*,chunk_t,chunk_t*))pkcs1_decrypt; - this->public.build_emsa_pkcs1_signature = (status_t (*) (rsa_private_key_t*,hash_algorithm_t,chunk_t,chunk_t*))build_emsa_pkcs1_signature; - this->public.pkcs1_write = (bool (*) (rsa_private_key_t*,const char*,bool))pkcs1_write; - this->public.get_public_key = (rsa_public_key_t* (*) (rsa_private_key_t*))get_public_key; - this->public.belongs_to = (bool (*) (rsa_private_key_t*,rsa_public_key_t*))belongs_to; - this->public.destroy = (void (*) (rsa_private_key_t*))destroy; - - /* private functions */ - this->rsadp = rsadp; - this->rsasp1 = rsadp; /* same algorithm */ - - this->keyid = chunk_empty; - - return this; -} - -/* - * See header - */ -rsa_private_key_t *rsa_private_key_create(size_t key_size) -{ - mpz_t p, q, n, e, d, exp1, exp2, coeff; - mpz_t m, q1, t; - private_rsa_private_key_t *this; - size_t key_len = key_size / BITS_PER_BYTE; - size_t prime_len = key_len / 2; - - /* Get values of primes p and q */ - if (compute_prime(this, prime_len, &p) != SUCCESS) - { - return NULL; - } - if (compute_prime(this, prime_len, &q) != SUCCESS) - { - mpz_clear(p); - return NULL; - } - - mpz_init(t); - mpz_init(n); - mpz_init(d); - mpz_init(exp1); - mpz_init(exp2); - mpz_init(coeff); - - /* Swapping Primes so p is larger then q */ - if (mpz_cmp(p, q) < 0) - { - mpz_swap(p, q); - } - - mpz_mul(n, p, q); /* n = p*q */ - mpz_init_set_ui(e, PUBLIC_EXPONENT); /* assign public exponent */ - mpz_init_set(m, p); /* m = p */ - mpz_sub_ui(m, m, 1); /* m = m -1 */ - mpz_init_set(q1, q); /* q1 = q */ - mpz_sub_ui(q1, q1, 1); /* q1 = q1 -1 */ - mpz_gcd(t, m, q1); /* t = gcd(p-1, q-1) */ - mpz_mul(m, m, q1); /* m = (p-1)*(q-1) */ - mpz_divexact(m, m, t); /* m = m / t */ - mpz_gcd(t, m, e); /* t = gcd(m, e) (greatest common divisor) */ - - mpz_invert(d, e, m); /* e has an inverse mod m */ - if (mpz_cmp_ui(d, 0) < 0) /* make sure d is positive */ - { - mpz_add(d, d, m); - } - mpz_sub_ui(t, p, 1); /* t = p-1 */ - mpz_mod(exp1, d, t); /* exp1 = d mod p-1 */ - mpz_sub_ui(t, q, 1); /* t = q-1 */ - mpz_mod(exp2, d, t); /* exp2 = d mod q-1 */ - - mpz_invert(coeff, q, p); /* coeff = q^-1 mod p */ - if (mpz_cmp_ui(coeff, 0) < 0) /* make coeff d is positive */ - { - mpz_add(coeff, coeff, p); - } - - mpz_clear_randomized(q1); - mpz_clear_randomized(m); - mpz_clear_randomized(t); - - /* determine exact the modulus size in bits */ - key_size = mpz_sizeinbase(n, 2); - - /* create and fill in rsa_private_key_t object */ - this = rsa_private_key_create_empty(); - this->k = (key_size + 7) / BITS_PER_BYTE; - this->keyid = rsa_public_key_id_create(n, e); - *(this->p) = *p; - *(this->q) = *q; - *(this->n) = *n; - *(this->e) = *e; - *(this->d) = *d; - *(this->exp1) = *exp1; - *(this->exp2) = *exp2; - *(this->coeff) = *coeff; - DBG1("generated %d bit RSA key with keyid: %#B", key_size, &this->keyid); - - return &this->public; -} - -/* - * see header - */ -rsa_private_key_t *rsa_private_key_create_from_chunk(chunk_t blob) -{ - asn1_ctx_t ctx; - chunk_t object; - u_int level; - int objectID = 0; - private_rsa_private_key_t *this; - - this = rsa_private_key_create_empty(); - - mpz_init(this->n); - mpz_init(this->e); - mpz_init(this->p); - mpz_init(this->q); - mpz_init(this->d); - mpz_init(this->exp1); - mpz_init(this->exp2); - mpz_init(this->coeff); - - asn1_init(&ctx, blob, 0, FALSE, TRUE); - - while (objectID < PRIV_KEY_ROOF) - { - if (!extract_object(privkey_objects, &objectID, &object, &level, &ctx)) - { - destroy(this); - return FALSE; - } - switch (objectID) - { - case PRIV_KEY_VERSION: - if (object.len > 0 && *object.ptr != 0) - { - destroy(this); - return NULL; - } - break; - case PRIV_KEY_MODULUS: - mpz_import(this->n, object.len, 1, 1, 1, 0, object.ptr); - break; - case PRIV_KEY_PUB_EXP: - mpz_import(this->e, object.len, 1, 1, 1, 0, object.ptr); - break; - case PRIV_KEY_PRIV_EXP: - mpz_import(this->d, object.len, 1, 1, 1, 0, object.ptr); - break; - case PRIV_KEY_PRIME1: - mpz_import(this->p, object.len, 1, 1, 1, 0, object.ptr); - break; - case PRIV_KEY_PRIME2: - mpz_import(this->q, object.len, 1, 1, 1, 0, object.ptr); - break; - case PRIV_KEY_EXP1: - mpz_import(this->exp1, object.len, 1, 1, 1, 0, object.ptr); - break; - case PRIV_KEY_EXP2: - mpz_import(this->exp2, object.len, 1, 1, 1, 0, object.ptr); - break; - case PRIV_KEY_COEFF: - mpz_import(this->coeff, object.len, 1, 1, 1, 0, object.ptr); - break; - } - objectID++; - } - - this->k = (mpz_sizeinbase(this->n, 2) + 7) / BITS_PER_BYTE; - this->keyid = rsa_public_key_id_create(this->n, this->e); - - if (check(this) != SUCCESS) - { - destroy(this); - return NULL; - } - else - { - return &this->public; - } -} - -/* - * see header - */ -rsa_private_key_t *rsa_private_key_create_from_file(char *filename, chunk_t *passphrase) -{ - bool pgp = FALSE; - chunk_t chunk = chunk_empty; - rsa_private_key_t *key = NULL; - - if (!pem_asn1_load_file(filename, passphrase, "private key", &chunk, &pgp)) - return NULL; - - key = rsa_private_key_create_from_chunk(chunk); - chunk_free_randomized(&chunk); - return key; -} diff --git a/src/libstrongswan/crypto/rsa/rsa_private_key.h b/src/libstrongswan/crypto/rsa/rsa_private_key.h deleted file mode 100644 index 8013f03c2..000000000 --- a/src/libstrongswan/crypto/rsa/rsa_private_key.h +++ /dev/null @@ -1,163 +0,0 @@ -/** - * @file rsa_private_key.h - * - * @brief Interface of rsa_private_key_t. - * - */ - -/* - * Copyright (C) 2005 Jan Hutter - * Copyright (C) 2005-2006 Martin Willi - * Copyright (C) 2007-2008 Andreas Steffen - * - * Hochschule fuer Technik Rapperswil - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * RCSID $Id: rsa_private_key.h 3423 2008-01-22 10:32:37Z andreas $ - */ - -#ifndef RSA_PRIVATE_KEY_H_ -#define RSA_PRIVATE_KEY_H_ - -typedef struct rsa_private_key_t rsa_private_key_t; - -#include <library.h> -#include <crypto/rsa/rsa_public_key.h> -#include <crypto/hashers/hasher.h> - -/** - * @brief RSA private key with associated functions. - * - * Currently only supports signing using EMSA encoding. - * - * @b Constructors: - * - rsa_private_key_create() - * - rsa_private_key_create_from_chunk() - * - rsa_private_key_create_from_file() - * - * @see rsa_public_key_t - * - * @ingroup rsa - */ -struct rsa_private_key_t { - - /** - * @brief Decrypt a data block based on EME-PKCS1 encoding. - * - * - * @param this calling object - * @param data encrypted input data - * @param out decrypted output data - * @return - * - SUCCESS - * - FAILED if padding is not correct - */ - status_t (*pkcs1_decrypt) (rsa_private_key_t *this, chunk_t in, chunk_t *out); - - /** - * @brief Build a signature over a chunk using EMSA-PKCS1 encoding. - * - * This signature creates a hash using the specified hash algorithm, concatenates - * it with an ASN1-OID of the hash algorithm and runs the RSASP1 function - * on it. - * - * @param this calling object - * @param hash_algorithm hash algorithm to use for hashing - * @param data data to sign - * @param[out] signature allocated signature - * @return - * - SUCCESS - * - INVALID_STATE, if key not set - * - NOT_SUPPORTED, if hash algorithm not supported - */ - status_t (*build_emsa_pkcs1_signature) (rsa_private_key_t *this, hash_algorithm_t hash_algorithm, chunk_t data, chunk_t *signature); - - /** - * @brief Writes an RSA private key to a file in PKCS#1 format. - * - * @param this calling object - * @param filename file to which the key should be written. - * @param force if TRUE overwrite existing file - * @return TRUE if successful - FALSE otherwise - */ - bool (*pkcs1_write) (rsa_private_key_t *this, const char *filename, bool force); - - /** - * @brief Create a rsa_public_key_t with the public part of the key. - * - * @param this calling object - * @return public_key - */ - rsa_public_key_t *(*get_public_key) (rsa_private_key_t *this); - - /** - * @brief Check if a private key belongs to a public key. - * - * Compares the public part of the private key with the - * public key, return TRUE if it equals. - * - * @param this private key - * @param public public key - * @return TRUE, if keys belong together - */ - bool (*belongs_to) (rsa_private_key_t *this, rsa_public_key_t *public); - - /** - * @brief Destroys the private key. - * - * @param this private key to destroy - */ - void (*destroy) (rsa_private_key_t *this); -}; - -/** - * @brief Generate a new RSA key with specified key length. - * - * @param key_size size of the key in bits - * @return generated rsa_private_key_t. - * - * @ingroup rsa - */ -rsa_private_key_t *rsa_private_key_create(size_t key_size); - -/** - * @brief Load an RSA private key from a chunk. - * - * Load a key from a chunk, encoded as described in PKCS#1 - * (ASN1 DER encoded). - * - * @param chunk chunk containing the DER encoded key - * @return loaded rsa_private_key_t, or NULL - * - * @ingroup rsa - */ -rsa_private_key_t *rsa_private_key_create_from_chunk(chunk_t chunk); - -/** - * @brief Load an RSA private key from a file. - * - * Load a key from a file, which is either in a unencrypted binary - * format (DER), or in a (encrypted) PEM format. The supplied - * passphrase is used to decrypt an ecrypted key. - * - * @param filename filename which holds the key - * @param passphrase optional passphase for decryption, can be NULL - * @return loaded rsa_private_key_t, or NULL - * - * @todo Implement PEM file loading - * @todo Implement key decryption - * - * @ingroup rsa - */ -rsa_private_key_t *rsa_private_key_create_from_file(char *filename, chunk_t *passphrase); - -#endif /*RSA_PRIVATE_KEY_H_*/ diff --git a/src/libstrongswan/crypto/rsa/rsa_public_key.c b/src/libstrongswan/crypto/rsa/rsa_public_key.c deleted file mode 100644 index 10af0527e..000000000 --- a/src/libstrongswan/crypto/rsa/rsa_public_key.c +++ /dev/null @@ -1,516 +0,0 @@ -/** - * @file rsa_public_key.c - * - * @brief Implementation of rsa_public_key_t. - * - */ - -/* - * Copyright (C) 2005 Jan Hutter - * Copyright (C) 2005-2006 Martin Willi - * Copyright (C) 2007-2008 Andreas Steffen - * - * Hochschule fuer Technik Rapperswil - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * RCSID $Id: rsa_public_key.c 3428 2008-01-27 20:58:52Z andreas $ - */ - -#include <gmp.h> -#include <sys/stat.h> -#include <unistd.h> -#include <stdio.h> -#include <string.h> - -#include "rsa_public_key.h" - -#include <debug.h> -#include <utils/randomizer.h> -#include <crypto/hashers/hasher.h> -#include <asn1/asn1.h> -#include <asn1/pem.h> - -/* ASN.1 definition of RSApublicKey */ -static const asn1Object_t pubkeyObjects[] = { - { 0, "RSAPublicKey", ASN1_SEQUENCE, ASN1_OBJ }, /* 0 */ - { 1, "modulus", ASN1_INTEGER, ASN1_BODY }, /* 1 */ - { 1, "publicExponent", ASN1_INTEGER, ASN1_BODY }, /* 2 */ -}; - -#define PUB_KEY_RSA_PUBLIC_KEY 0 -#define PUB_KEY_MODULUS 1 -#define PUB_KEY_EXPONENT 2 -#define PUB_KEY_ROOF 3 - -/* ASN.1 definition of digestInfo */ -static const asn1Object_t digestInfoObjects[] = { - { 0, "digestInfo", ASN1_SEQUENCE, ASN1_OBJ }, /* 0 */ - { 1, "digestAlgorithm", ASN1_EOC, ASN1_RAW }, /* 1 */ - { 1, "digest", ASN1_OCTET_STRING, ASN1_BODY }, /* 2 */ -}; - -#define DIGEST_INFO 0 -#define DIGEST_INFO_ALGORITHM 1 -#define DIGEST_INFO_DIGEST 2 -#define DIGEST_INFO_ROOF 3 - -typedef struct private_rsa_public_key_t private_rsa_public_key_t; - -/** - * Private data structure with signing context. - */ -struct private_rsa_public_key_t { - /** - * Public interface for this signer. - */ - rsa_public_key_t public; - - /** - * Public modulus. - */ - mpz_t n; - - /** - * Public exponent. - */ - mpz_t e; - - /** - * Keysize in bytes. - */ - size_t k; - - /** - * Keyid formed as a SHA-1 hash of a publicKeyInfo object - */ - chunk_t keyid; - - /** - * @brief Implements the RSAEP algorithm specified in PKCS#1. - * - * @param this calling object - * @param data data to process - * @return processed data - */ - chunk_t (*rsaep) (const private_rsa_public_key_t *this, chunk_t data); - - /** - * @brief Implements the RSASVP1 algorithm specified in PKCS#1. - * - * @param this calling object - * @param data data to process - * @return processed data - */ - chunk_t (*rsavp1) (const private_rsa_public_key_t *this, chunk_t data); -}; - -/** - * Implementation of private_rsa_public_key_t.rsaep and private_rsa_public_key_t.rsavp1 - */ -static chunk_t rsaep(const private_rsa_public_key_t *this, chunk_t data) -{ - mpz_t m, c; - chunk_t encrypted; - - mpz_init(c); - mpz_init(m); - - mpz_import(m, data.len, 1, 1, 1, 0, data.ptr); - - mpz_powm(c, m, this->e, this->n); - - encrypted.len = this->k; - encrypted.ptr = mpz_export(NULL, NULL, 1, encrypted.len, 1, 0, c); - - mpz_clear(c); - mpz_clear(m); - - return encrypted; -} - -/** - * Implementation of rsa_public_key_t.eme_pkcs1_encrypt. - */ -static status_t pkcs1_encrypt(private_rsa_public_key_t *this, - chunk_t in, chunk_t *out) -{ - chunk_t em; - u_char *pos; - int padding = this->k - in.len - 3; - - if (padding < 8) - { - DBG1("rsa padding of %d bytes is too small", padding); - return FAILED; - } - em.len = this->k; - em.ptr = pos = malloc(em.len); - - /* add padding according to PKCS#1 7.2.1 1.+2. */ - *pos++ = 0x00; - *pos++ = 0x02; - - /* pad with pseudo random bytes unequal to zero */ - { - randomizer_t *randomizer = randomizer_create(); - - /* pad with pseudo random bytes unequal to zero */ - while (padding--) - { - randomizer->get_pseudo_random_bytes(randomizer, 1, pos); - while (!*pos) - { - randomizer->get_pseudo_random_bytes(randomizer, 1, pos); - } - pos++; - } - randomizer->destroy(randomizer); - } - - /* append the padding terminator */ - *pos++ = 0x00; - - /* now add the data */ - memcpy(pos, in.ptr, in.len); - *out = this->rsaep(this, em); - free(em.ptr); - return SUCCESS; -} - -/** - * Implementation of rsa_public_key.verify_emsa_pkcs1_signature. - */ -static status_t verify_emsa_pkcs1_signature(const private_rsa_public_key_t *this, - hash_algorithm_t algorithm, - chunk_t data, chunk_t signature) -{ - chunk_t em_ori, em; - status_t res = FAILED; - - /* remove any preceding 0-bytes from signature */ - while (signature.len && *(signature.ptr) == 0x00) - { - signature.len -= 1; - signature.ptr++; - } - - if (signature.len > this->k) - { - return INVALID_ARG; - } - - /* unpack signature */ - em_ori = em = this->rsavp1(this, signature); - - /* result should look like this: - * EM = 0x00 || 0x01 || PS || 0x00 || T. - * PS = 0xFF padding, with length to fill em - * T = oid || hash - */ - - /* check magic bytes */ - if (*(em.ptr) != 0x00 || *(em.ptr+1) != 0x01) - { - DBG2("incorrect padding - probably wrong RSA key"); - goto end; - } - em.ptr += 2; - em.len -= 2; - - /* find magic 0x00 */ - while (em.len > 0) - { - if (*em.ptr == 0x00) - { - /* found magic byte, stop */ - em.ptr++; - em.len--; - break; - } - else if (*em.ptr != 0xFF) - { - /* bad padding, decryption failed ?!*/ - goto end; - } - em.ptr++; - em.len--; - } - - if (em.len == 0) - { - /* no digestInfo found */ - goto end; - } - - /* parse ASN.1-based digestInfo */ - { - asn1_ctx_t ctx; - chunk_t object; - u_int level; - int objectID = 0; - hash_algorithm_t hash_algorithm = HASH_UNKNOWN; - - asn1_init(&ctx, em, 0, FALSE, FALSE); - - while (objectID < DIGEST_INFO_ROOF) - { - if (!extract_object(digestInfoObjects, &objectID, &object, &level, &ctx)) - { - goto end; - } - switch (objectID) - { - case DIGEST_INFO: - if (em.len > object.len) - { - DBG1("digestInfo field in signature is followed by %u surplus bytes", - em.len - object.len); - goto end; - } - break; - case DIGEST_INFO_ALGORITHM: - { - int hash_oid = parse_algorithmIdentifier(object, level+1, NULL); - - hash_algorithm = hasher_algorithm_from_oid(hash_oid); - if (hash_algorithm == HASH_UNKNOWN - || (algorithm != HASH_UNKNOWN && hash_algorithm != algorithm)) - { - DBG1("wrong hash algorithm used in signature"); - goto end; - } - } - break; - case DIGEST_INFO_DIGEST: - { - chunk_t hash; - hasher_t *hasher = hasher_create(hash_algorithm); - - if (object.len != hasher->get_hash_size(hasher)) - { - DBG1("hash size in signature is %u bytes instead of %u bytes", - object.len, hasher->get_hash_size(hasher)); - hasher->destroy(hasher); - goto end; - } - - /* build our own hash */ - hasher->allocate_hash(hasher, data, &hash); - hasher->destroy(hasher); - - /* compare the hashes */ - res = memeq(object.ptr, hash.ptr, hash.len) ? SUCCESS : FAILED; - free(hash.ptr); - } - break; - default: - break; - } - objectID++; - } - } - -end: - free(em_ori.ptr); - return res; -} - - -/** - * Implementation of rsa_public_key_t.get_modulus. - */ -static mpz_t *get_modulus(const private_rsa_public_key_t *this) -{ - return (mpz_t*)&this->n; -} - -/** - * Implementation of rsa_public_key_t.get_keysize. - */ -static size_t get_keysize(const private_rsa_public_key_t *this) -{ - return this->k; -} - -/** - * Build a DER-encoded publicKeyInfo object from an RSA public key. - * Also used in rsa_private_key.c. - */ -chunk_t rsa_public_key_info_to_asn1(const mpz_t n, const mpz_t e) -{ - chunk_t publicKey = asn1_wrap(ASN1_SEQUENCE, "mm", - asn1_integer_from_mpz(n), - asn1_integer_from_mpz(e)); - - return asn1_wrap(ASN1_SEQUENCE, "cm", - asn1_algorithmIdentifier(OID_RSA_ENCRYPTION), - asn1_bitstring("m", publicKey)); -} - -/** - * Form the RSA keyid as a SHA-1 hash of a publicKeyInfo object - * Also used in rsa_private_key.c. - */ -chunk_t rsa_public_key_id_create(mpz_t n, mpz_t e) -{ - chunk_t keyid; - chunk_t publicKeyInfo = rsa_public_key_info_to_asn1(n, e); - hasher_t *hasher = hasher_create(HASH_SHA1); - - hasher->allocate_hash(hasher, publicKeyInfo, &keyid); - hasher->destroy(hasher); - free(publicKeyInfo.ptr); - - return keyid; -} - -/** - * Implementation of rsa_public_key_t.get_publicKeyInfo. - */ -static chunk_t get_publicKeyInfo(const private_rsa_public_key_t *this) -{ - return rsa_public_key_info_to_asn1(this->n, this->e); -} - -/** - * Implementation of rsa_public_key_t.get_keyid. - */ -static chunk_t get_keyid(const private_rsa_public_key_t *this) -{ - return this->keyid; -} - -/* forward declaration used by rsa_public_key_t.clone */ -private_rsa_public_key_t *rsa_public_key_create_empty(void); - -/** - * Implementation of rsa_public_key_t.clone. - */ -static rsa_public_key_t* _clone(const private_rsa_public_key_t *this) -{ - private_rsa_public_key_t *clone = rsa_public_key_create_empty(); - - mpz_init_set(clone->n, this->n); - mpz_init_set(clone->e, this->e); - clone->keyid = chunk_clone(this->keyid); - clone->k = this->k; - - return &clone->public; -} - -/** - * Implementation of rsa_public_key_t.destroy. - */ -static void destroy(private_rsa_public_key_t *this) -{ - mpz_clear(this->n); - mpz_clear(this->e); - free(this->keyid.ptr); - free(this); -} - -/** - * Generic private constructor - */ -private_rsa_public_key_t *rsa_public_key_create_empty(void) -{ - private_rsa_public_key_t *this = malloc_thing(private_rsa_public_key_t); - - /* public functions */ - this->public.pkcs1_encrypt = (status_t (*) (rsa_public_key_t*,chunk_t,chunk_t*))pkcs1_encrypt; - this->public.verify_emsa_pkcs1_signature = (status_t (*) (const rsa_public_key_t*,hash_algorithm_t,chunk_t,chunk_t))verify_emsa_pkcs1_signature; - this->public.get_modulus = (mpz_t *(*) (const rsa_public_key_t*))get_modulus; - this->public.get_keysize = (size_t (*) (const rsa_public_key_t*))get_keysize; - this->public.get_publicKeyInfo = (chunk_t (*) (const rsa_public_key_t*))get_publicKeyInfo; - this->public.get_keyid = (chunk_t (*) (const rsa_public_key_t*))get_keyid; - this->public.clone = (rsa_public_key_t* (*) (const rsa_public_key_t*))_clone; - this->public.destroy = (void (*) (rsa_public_key_t*))destroy; - - /* private functions */ - this->rsaep = rsaep; - this->rsavp1 = rsaep; /* same algorithm */ - - return this; -} - -/* - * See header - */ -rsa_public_key_t *rsa_public_key_create(mpz_t n, mpz_t e) -{ - private_rsa_public_key_t *this = rsa_public_key_create_empty(); - - mpz_init_set(this->n, n); - mpz_init_set(this->e, e); - - this->k = (mpz_sizeinbase(n, 2) + 7) / BITS_PER_BYTE; - this->keyid = rsa_public_key_id_create(n, e); - return &this->public; -} -/* - * See header - */ -rsa_public_key_t *rsa_public_key_create_from_chunk(chunk_t blob) -{ - asn1_ctx_t ctx; - chunk_t object; - u_int level; - int objectID = 0; - - private_rsa_public_key_t *this = rsa_public_key_create_empty(); - - mpz_init(this->n); - mpz_init(this->e); - - asn1_init(&ctx, blob, 0, FALSE, FALSE); - - while (objectID < PUB_KEY_ROOF) - { - if (!extract_object(pubkeyObjects, &objectID, &object, &level, &ctx)) - { - destroy(this); - return FALSE; - } - switch (objectID) - { - case PUB_KEY_MODULUS: - mpz_import(this->n, object.len, 1, 1, 1, 0, object.ptr); - break; - case PUB_KEY_EXPONENT: - mpz_import(this->e, object.len, 1, 1, 1, 0, object.ptr); - break; - } - objectID++; - } - - this->k = (mpz_sizeinbase(this->n, 2) + 7) / BITS_PER_BYTE; - this->keyid = rsa_public_key_id_create(this->n, this->e); - return &this->public; -} - -/* - * See header - */ -rsa_public_key_t *rsa_public_key_create_from_file(char *filename) -{ - bool pgp = FALSE; - chunk_t chunk = chunk_empty; - rsa_public_key_t *pubkey = NULL; - - if (!pem_asn1_load_file(filename, NULL, "public key", &chunk, &pgp)) - { - return NULL; - } - pubkey = rsa_public_key_create_from_chunk(chunk); - free(chunk.ptr); - return pubkey; -} diff --git a/src/libstrongswan/crypto/rsa/rsa_public_key.h b/src/libstrongswan/crypto/rsa/rsa_public_key.h deleted file mode 100644 index c0bd3e351..000000000 --- a/src/libstrongswan/crypto/rsa/rsa_public_key.h +++ /dev/null @@ -1,173 +0,0 @@ -/** - * @file rsa_public_key.h - * - * @brief Interface of rsa_public_key_t. - * - */ - -/* - * Copyright (C) 2005 Jan Hutter - * Copyright (C) 2005-2006 Martin Willi - * Copyright (C) 2007-2008 Andreas Steffen - * - * Hochschule fuer Technik Rapperswil - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * RCSID $Id: rsa_public_key.h 3423 2008-01-22 10:32:37Z andreas $ - */ - -#ifndef RSA_PUBLIC_KEY_H_ -#define RSA_PUBLIC_KEY_H_ - -typedef struct rsa_public_key_t rsa_public_key_t; - -#include <gmp.h> - -#include <library.h> -#include <crypto/hashers/hasher.h> - -/** - * @brief RSA public key with associated functions. - * - * Currently only supports signature verification using - * the EMSA encoding (see PKCS1) - * - * @b Constructors: - * - rsa_public_key_create() - * - rsa_public_key_create_from_chunk() - * - rsa_public_key_create_from_file() - * - * @ingroup rsa - */ -struct rsa_public_key_t { - - /** - * @brief Encrypt a data block using EME-PKCS1 encoding. - * - * - * @param this calling object - * @param data plaintext input data - * @param out encrypted output data - * @return - * - SUCCESS - * - FAILED if data block is too large - */ - status_t (*pkcs1_encrypt) (rsa_public_key_t *this, chunk_t in, chunk_t *out); - - /** - * @brief Verify an EMSA-PKCS1 encoded signature. - * - * Processes the supplied signature with the RSAVP1 function, - * selects the hash algorithm form the resultign ASN1-OID and - * verifies the hash against the supplied data. - * - * @param this rsa_public_key to use - * @param data data to sign - # @param algorithm hash algorithm the signature is based on - * @param signature signature to verify - * @return - * - SUCCESS, if signature ok - * - INVALID_STATE, if key not set - * - NOT_SUPPORTED, if hash algorithm not supported - * - INVALID_ARG, if signature is not a signature - * - FAILED if signature invalid or unable to verify - */ - status_t (*verify_emsa_pkcs1_signature) (const rsa_public_key_t *this, - hash_algorithm_t algorithm, - chunk_t data, chunk_t signature); - - /** - * @brief Get the modulus of the key. - * - * @param this calling object - * @return modulus (n) of the key - */ - mpz_t *(*get_modulus) (const rsa_public_key_t *this); - - /** - * @brief Get the size of the modulus in bytes. - * - * @param this calling object - * @return size of the modulus (n) in bytes - */ - size_t (*get_keysize) (const rsa_public_key_t *this); - - /** - * @brief Get the DER encoded publicKeyInfo object. - * - * @param this calling object - * @return DER encoded publicKeyInfo object - */ - chunk_t (*get_publicKeyInfo) (const rsa_public_key_t *this); - - /** - * @brief Get the keyid formed as the SHA-1 hash of a publicKeyInfo object. - * - * @param this calling object - * @return keyid in the form of a SHA-1 hash - */ - chunk_t (*get_keyid) (const rsa_public_key_t *this); - - /** - * @brief Clone the public key. - * - * @param this public key to clone - * @return clone of this - */ - rsa_public_key_t *(*clone) (const rsa_public_key_t *this); - - /** - * @brief Destroys the public key. - * - * @param this public key to destroy - */ - void (*destroy) (rsa_public_key_t *this); -}; - -/** - * @brief Create a RSA public key from modulus and public exponent. - * - * @param n modulus - * @param e public exponent - * @return created rsa_public_key_t - * - * @ingroup rsa - */ -rsa_public_key_t *rsa_public_key_create(mpz_t n, mpz_t e); - -/** - * @brief Load an RSA public key from a chunk. - * - * Load a key from a chunk, encoded in the more frequently - * used publicKeyInfo object (ASN1 DER encoded). - * - * @param chunk chunk containing the DER encoded key - * @return loaded rsa_public_key_t, or NULL - * - * @ingroup rsa - */ -rsa_public_key_t *rsa_public_key_create_from_chunk(chunk_t chunk); - -/** - * @brief Load an RSA public key from a file. - * - * Load a key from a file, which is either in binary - * format (DER), or in PEM format. - * - * @param filename filename which holds the key - * @return loaded rsa_public_key_t, or NULL - * - * @ingroup rsa - */ -rsa_public_key_t *rsa_public_key_create_from_file(char *filename); - -#endif /*RSA_PUBLIC_KEY_H_*/ diff --git a/src/libstrongswan/crypto/signers/hmac_signer.c b/src/libstrongswan/crypto/signers/hmac_signer.c deleted file mode 100644 index ad5b882a6..000000000 --- a/src/libstrongswan/crypto/signers/hmac_signer.c +++ /dev/null @@ -1,185 +0,0 @@ -/** - * @file hmac_signer.c - * - * @brief Implementation of hmac_signer_t. - * - */ - -/* - * Copyright (C) 2005-2006 Martin Willi - * Copyright (C) 2005 Jan Hutter - * Hochschule fuer Technik Rapperswil - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -#include <string.h> - -#include "hmac_signer.h" - -#include <crypto/prfs/hmac_prf.h> - -typedef struct private_hmac_signer_t private_hmac_signer_t; - -/** - * Private data structure with signing context. - */ -struct private_hmac_signer_t { - /** - * Public interface of hmac_signer_t. - */ - hmac_signer_t public; - - /** - * Assigned hmac function. - */ - prf_t *hmac_prf; - - /** - * Block size (truncation of HMAC Hash) - */ - size_t block_size; -}; - -/** - * Implementation of signer_t.get_signature. - */ -static void get_signature(private_hmac_signer_t *this, chunk_t data, u_int8_t *buffer) -{ - if (buffer == NULL) - { /* append mode */ - this->hmac_prf->get_bytes(this->hmac_prf, data, NULL); - } - else - { - u_int8_t full_mac[this->hmac_prf->get_block_size(this->hmac_prf)]; - - this->hmac_prf->get_bytes(this->hmac_prf, data, full_mac); - memcpy(buffer, full_mac, this->block_size); - } -} - -/** - * Implementation of signer_t.allocate_signature. - */ -static void allocate_signature (private_hmac_signer_t *this, chunk_t data, chunk_t *chunk) -{ - if (chunk == NULL) - { /* append mode */ - this->hmac_prf->get_bytes(this->hmac_prf, data, NULL); - } - else - { - chunk_t signature; - u_int8_t full_mac[this->hmac_prf->get_block_size(this->hmac_prf)]; - - this->hmac_prf->get_bytes(this->hmac_prf, data, full_mac); - - signature.ptr = malloc(this->block_size); - signature.len = this->block_size; - - memcpy(signature.ptr, full_mac, this->block_size); - - *chunk = signature; - } -} - -/** - * Implementation of signer_t.verify_signature. - */ -static bool verify_signature(private_hmac_signer_t *this, chunk_t data, chunk_t signature) -{ - u_int8_t full_mac[this->hmac_prf->get_block_size(this->hmac_prf)]; - - this->hmac_prf->get_bytes(this->hmac_prf, data, full_mac); - - if (signature.len != this->block_size) - { - return FALSE; - } - - /* compare mac aka signature :-) */ - if (memcmp(signature.ptr, full_mac, this->block_size) == 0) - { - return TRUE; - } - else - { - return FALSE; - } -} - -/** - * Implementation of signer_t.get_key_size. - */ -static size_t get_key_size(private_hmac_signer_t *this) -{ - /* for HMAC signer, IKEv2 uses block size as key size */ - return this->hmac_prf->get_block_size(this->hmac_prf); -} - -/** - * Implementation of signer_t.get_block_size. - */ -static size_t get_block_size(private_hmac_signer_t *this) -{ - return this->block_size; -} - -/** - * Implementation of signer_t.set_key. - */ -static void set_key(private_hmac_signer_t *this, chunk_t key) -{ - this->hmac_prf->set_key(this->hmac_prf, key); -} - -/** - * Implementation of signer_t.destroy. - */ -static status_t destroy(private_hmac_signer_t *this) -{ - this->hmac_prf->destroy(this->hmac_prf); - free(this); - return SUCCESS; -} - -/* - * Described in header - */ -hmac_signer_t *hmac_signer_create(hash_algorithm_t hash_algoritm, size_t block_size) -{ - size_t hmac_block_size; - private_hmac_signer_t *this = malloc_thing(private_hmac_signer_t); - - this->hmac_prf = (prf_t *) hmac_prf_create(hash_algoritm); - if (this->hmac_prf == NULL) - { - /* algorithm not supported */ - free(this); - return NULL; - } - - /* prevent invalid truncation */ - hmac_block_size = this->hmac_prf->get_block_size(this->hmac_prf); - this->block_size = min(block_size, hmac_block_size); - - /* interface functions */ - this->public.signer_interface.get_signature = (void (*) (signer_t*, chunk_t, u_int8_t*))get_signature; - this->public.signer_interface.allocate_signature = (void (*) (signer_t*, chunk_t, chunk_t*))allocate_signature; - this->public.signer_interface.verify_signature = (bool (*) (signer_t*, chunk_t, chunk_t))verify_signature; - this->public.signer_interface.get_key_size = (size_t (*) (signer_t*))get_key_size; - this->public.signer_interface.get_block_size = (size_t (*) (signer_t*))get_block_size; - this->public.signer_interface.set_key = (void (*) (signer_t*,chunk_t))set_key; - this->public.signer_interface.destroy = (void (*) (signer_t*))destroy; - - return &(this->public); -} diff --git a/src/libstrongswan/crypto/signers/hmac_signer.h b/src/libstrongswan/crypto/signers/hmac_signer.h deleted file mode 100644 index 2449069bd..000000000 --- a/src/libstrongswan/crypto/signers/hmac_signer.h +++ /dev/null @@ -1,68 +0,0 @@ -/** - * @file hmac_signer.h - * - * @brief Interface of hmac_signer_t. - * - */ - -/* - * Copyright (C) 2005-2006 Martin Willi - * Copyright (C) 2005 Jan Hutter - * Hochschule fuer Technik Rapperswil - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -#ifndef HMAC_SIGNER_H_ -#define HMAC_SIGNER_H_ - -typedef struct hmac_signer_t hmac_signer_t; - -#include <crypto/signers/signer.h> -#include <crypto/hashers/hasher.h> - -/** - * @brief Implementation of signer_t interface using HMAC. - * - * HMAC uses a standard hash function implemented in a hasher_t to build - * a MAC. - * - * @ingroup signers - */ -struct hmac_signer_t { - - /** - * generic signer_t interface for this signer - */ - signer_t signer_interface; -}; - -/** - * @brief Creates a new hmac_signer_t. - * - * HMAC signatures are often truncated to shorten them to a more usable, but - * still secure enough length. - * Block size must be equal or smaller then the hash algorithms - * hash. - * - * @param hash_algoritm Hash algorithm to use with signer - * @param block_size Size of resulting signature (truncated to block_size) - * @return - * - hmac_signer_t - * - NULL if hash algorithm not supported - * - * @ingroup signers - */ -hmac_signer_t *hmac_signer_create(hash_algorithm_t hash_algoritm, - size_t block_size); - - -#endif /*HMAC_SIGNER_H_*/ diff --git a/src/libstrongswan/crypto/signers/signer.c b/src/libstrongswan/crypto/signers/signer.c index 747bc5efa..8412ff62e 100644 --- a/src/libstrongswan/crypto/signers/signer.c +++ b/src/libstrongswan/crypto/signers/signer.c @@ -1,10 +1,3 @@ -/** - * @file signer.c - * - * @brief Implementation of generic signer_t constructor. - * - */ - /* * Copyright (C) 2005-2006 Martin Willi * Copyright (C) 2005 Jan Hutter @@ -19,12 +12,12 @@ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. + * + * $Id: signer.c 3589 2008-03-13 14:14:44Z martin $ */ #include "signer.h" -#include <crypto/signers/hmac_signer.h> - ENUM_BEGIN(integrity_algorithm_names, AUTH_UNDEFINED, AUTH_HMAC_SHA1_128, "UNDEFINED", "AUTH_HMAC_SHA1_128"); @@ -40,26 +33,3 @@ ENUM_NEXT(integrity_algorithm_names, AUTH_HMAC_SHA2_256_128, AUTH_HMAC_SHA2_512_ "AUTH_HMAC_SHA2_512_256"); ENUM_END(integrity_algorithm_names, AUTH_HMAC_SHA2_512_256); -/* - * Described in header. - */ -signer_t *signer_create(integrity_algorithm_t integrity_algorithm) -{ - switch(integrity_algorithm) - { - case AUTH_HMAC_SHA1_96: - return (signer_t *)hmac_signer_create(HASH_SHA1, 12); - case AUTH_HMAC_SHA1_128: - return (signer_t *)hmac_signer_create(HASH_SHA1, 16); - case AUTH_HMAC_MD5_96: - return (signer_t *)hmac_signer_create(HASH_MD5, 12); - case AUTH_HMAC_SHA2_256_128: - return (signer_t *)hmac_signer_create(HASH_SHA256, 16); - case AUTH_HMAC_SHA2_384_192: - return (signer_t *)hmac_signer_create(HASH_SHA384, 24); - case AUTH_HMAC_SHA2_512_256: - return (signer_t *)hmac_signer_create(HASH_SHA512, 32); - default: - return NULL; - } -} diff --git a/src/libstrongswan/crypto/signers/signer.h b/src/libstrongswan/crypto/signers/signer.h index 4218e4146..f67c38f07 100644 --- a/src/libstrongswan/crypto/signers/signer.h +++ b/src/libstrongswan/crypto/signers/signer.h @@ -1,10 +1,3 @@ -/** - * @file signer.h - * - * @brief Interface for signer_t. - * - */ - /* * Copyright (C) 2005-2006 Martin Willi * Copyright (C) 2005 Jan Hutter @@ -19,6 +12,13 @@ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. + * + * $Id: signer.h 3589 2008-03-13 14:14:44Z martin $ + */ + +/** + * @defgroup signer signer + * @{ @ingroup crypto */ #ifndef SIGNER_H_ @@ -30,11 +30,9 @@ typedef struct signer_t signer_t; #include <library.h> /** - * @brief Integrity algorithm, as in IKEv2 RFC 3.3.2. + * Integrity algorithm, as in IKEv2 RFC 3.3.2. * * Algorithms not specified in IKEv2 are allocated in private use space. - * - * @ingroup signers */ enum integrity_algorithm_t { AUTH_UNDEFINED = 1024, @@ -61,93 +59,65 @@ enum integrity_algorithm_t { extern enum_name_t *integrity_algorithm_names; /** - * @brief Generig interface for a symmetric signature algorithm. - * - * @b Constructors: - * - signer_create() - * - hmac_signer_create() - * - * @todo Implement more integrity algorithms - * - * @ingroup signers + * Generig interface for a symmetric signature algorithm. */ struct signer_t { /** - * @brief Generate a signature. + * Generate a signature. * * If buffer is NULL, data is processed and prepended to a next call until * buffer is a valid pointer. * - * @param this calling object - * @param data a chunk containing the data to sign - * @param[out] buffer pointer where the signature will be written + * @param data a chunk containing the data to sign + * @param buffer pointer where the signature will be written */ void (*get_signature) (signer_t *this, chunk_t data, u_int8_t *buffer); /** - * @brief Generate a signature and allocate space for it. + * Generate a signature and allocate space for it. * * If chunk is NULL, data is processed and prepended to a next call until * chunk is a valid chunk pointer. * - * @param this calling object - * @param data a chunk containing the data to sign - * @param[out] chunk chunk which will hold the allocated signature + * @param data a chunk containing the data to sign + * @param chunk chunk which will hold the allocated signature */ void (*allocate_signature) (signer_t *this, chunk_t data, chunk_t *chunk); /** - * @brief Verify a signature. + * Verify a signature. * - * @param this calling object - * @param data a chunk containing the data to verify - * @param signature a chunk containing the signature - * @return TRUE, if signature is valid, FALSE otherwise + * @param data a chunk containing the data to verify + * @param signature a chunk containing the signature + * @return TRUE, if signature is valid, FALSE otherwise */ bool (*verify_signature) (signer_t *this, chunk_t data, chunk_t signature); /** - * @brief Get the block size of this signature algorithm. + * Get the block size of this signature algorithm. * - * @param this calling object - * @return block size in bytes + * @return block size in bytes */ size_t (*get_block_size) (signer_t *this); /** - * @brief Get the key size of the signature algorithm. + * Get the key size of the signature algorithm. * - * @param this calling object - * @return key size in bytes + * @return key size in bytes */ size_t (*get_key_size) (signer_t *this); /** - * @brief Set the key for this object. + * Set the key for this object. * - * @param this calling object - * @param key key to set + * @param key key to set */ void (*set_key) (signer_t *this, chunk_t key); /** - * @brief Destroys a signer_t object. - * - * @param this calling object + * Destroys a signer_t object. */ void (*destroy) (signer_t *this); }; -/** - * @brief Creates a new signer_t object. - * - * @param integrity_algorithm Algorithm to use for signing and verifying. - * @return - * - signer_t object - * - NULL if signer not supported - * - * @ingroup signers - */ -signer_t *signer_create(integrity_algorithm_t integrity_algorithm); - -#endif /*SIGNER_H_*/ +#endif /*SIGNER_H_ @} */ diff --git a/src/libstrongswan/crypto/x509.c b/src/libstrongswan/crypto/x509.c deleted file mode 100755 index eadf11327..000000000 --- a/src/libstrongswan/crypto/x509.c +++ /dev/null @@ -1,1562 +0,0 @@ -/** - * @file x509.c - * - * @brief Implementation of x509_t. - * - */ - -/* - * Copyright (C) 2000 Andreas Hess, Patric Lichtsteiner, Roger Wegmann - * Copyright (C) 2001 Marco Bertossa, Andreas Schleiss - * Copyright (C) 2002 Mario Strasser - * Copyright (C) 2006 Martin Willi - * Copyright (C) 2000-2008 Andreas Steffen - * - * Hochschule fuer Technik Rapperswil - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * RCSID $Id: x509.c 3423 2008-01-22 10:32:37Z andreas $ - */ - -#include <gmp.h> -#include <sys/stat.h> -#include <unistd.h> -#include <string.h> -#include <stdio.h> - -#include "x509.h" -#include "hashers/hasher.h" -#include <library.h> -#include <debug.h> -#include <asn1/oid.h> -#include <asn1/asn1.h> -#include <asn1/pem.h> -#include <utils/linked_list.h> -#include <utils/identification.h> - -#define CERT_WARNING_INTERVAL 30 /* days */ - -/** - * Different kinds of generalNames - */ -typedef enum generalNames_t generalNames_t; - -enum generalNames_t { - GN_OTHER_NAME = 0, - GN_RFC822_NAME = 1, - GN_DNS_NAME = 2, - GN_X400_ADDRESS = 3, - GN_DIRECTORY_NAME = 4, - GN_EDI_PARTY_NAME = 5, - GN_URI = 6, - GN_IP_ADDRESS = 7, - GN_REGISTERED_ID = 8, -}; - -typedef struct private_x509_t private_x509_t; - -/** - * Private data of a x509_t object. - */ -struct private_x509_t { - /** - * Public interface for this certificate. - */ - x509_t public; - - /** - * Time when certificate was installed - */ - time_t installed; - - /** - * Time until certificate can be trusted - */ - time_t until; - - /** - * Certificate status - */ - cert_status_t status; - - /** - * Authority flags - */ - u_int authority_flags; - - /** - * X.509 Certificate in DER format - */ - chunk_t certificate; - - /** - * X.509 certificate body over which signature is computed - */ - chunk_t tbsCertificate; - - /** - * Version of the X.509 certificate - */ - u_int version; - - /** - * Serial number of the X.509 certificate - */ - chunk_t serialNumber; - - /** - * Signature algorithm - */ - int signatureAlgorithm; - - /** - * ID representing the certificate issuer - */ - identification_t *issuer; - - /** - * link to the info recored of the certificate issuer - */ - ca_info_t *ca_info; - - /** - * Start time of certificate validity - */ - time_t notBefore; - - /** - * End time of certificate validity - */ - time_t notAfter; - - /** - * ID representing the certificate subject - */ - identification_t *subject; - - /** - * List of identification_t's representing subjectAltNames - */ - linked_list_t *subjectAltNames; - - /** - * List of identification_t's representing crlDistributionPoints - */ - linked_list_t *crlDistributionPoints; - - /** - * List of identification_t's representing ocspAccessLocations - */ - linked_list_t *ocspAccessLocations; - - /** - * Subject public key - */ - chunk_t subjectPublicKey; - - /** - * Subject RSA public key, if subjectPublicKeyAlgorithm == RSA - */ - rsa_public_key_t *public_key; - - /** - * Subject Key Identifier - */ - chunk_t subjectKeyID; - - /** - * Authority Key Identifier - */ - chunk_t authKeyID; - - /** - * Authority Key Serial Number - */ - chunk_t authKeySerialNumber; - - /** - * Indicates if the certificate is self-signed - */ - bool isSelfSigned; - - /** - * CA basic constraints flag - */ - bool isCA; - - /** - * OCSPSigner extended key usage flag - */ - bool isOcspSigner; - - /** - * Signature - */ - chunk_t signature; - -}; - -/** - * ASN.1 definition of generalName - */ -static const asn1Object_t generalNameObjects[] = { - { 0, "otherName", ASN1_CONTEXT_C_0, ASN1_OPT|ASN1_BODY }, /* 0 */ - { 0, "end choice", ASN1_EOC, ASN1_END }, /* 1 */ - { 0, "rfc822Name", ASN1_CONTEXT_S_1, ASN1_OPT|ASN1_BODY }, /* 2 */ - { 0, "end choice", ASN1_EOC, ASN1_END }, /* 3 */ - { 0, "dnsName", ASN1_CONTEXT_S_2, ASN1_OPT|ASN1_BODY }, /* 4 */ - { 0, "end choice", ASN1_EOC, ASN1_END }, /* 5 */ - { 0, "x400Address", ASN1_CONTEXT_S_3, ASN1_OPT|ASN1_BODY }, /* 6 */ - { 0, "end choice", ASN1_EOC, ASN1_END }, /* 7 */ - { 0, "directoryName", ASN1_CONTEXT_C_4, ASN1_OPT|ASN1_BODY }, /* 8 */ - { 0, "end choice", ASN1_EOC, ASN1_END }, /* 9 */ - { 0, "ediPartyName", ASN1_CONTEXT_C_5, ASN1_OPT|ASN1_BODY }, /* 10 */ - { 0, "end choice", ASN1_EOC, ASN1_END }, /* 11 */ - { 0, "URI", ASN1_CONTEXT_S_6, ASN1_OPT|ASN1_BODY }, /* 12 */ - { 0, "end choice", ASN1_EOC, ASN1_END }, /* 13 */ - { 0, "ipAddress", ASN1_CONTEXT_S_7, ASN1_OPT|ASN1_BODY }, /* 14 */ - { 0, "end choice", ASN1_EOC, ASN1_END }, /* 15 */ - { 0, "registeredID", ASN1_CONTEXT_S_8, ASN1_OPT|ASN1_BODY }, /* 16 */ - { 0, "end choice", ASN1_EOC, ASN1_END } /* 17 */ -}; -#define GN_OBJ_OTHER_NAME 0 -#define GN_OBJ_RFC822_NAME 2 -#define GN_OBJ_DNS_NAME 4 -#define GN_OBJ_X400_ADDRESS 6 -#define GN_OBJ_DIRECTORY_NAME 8 -#define GN_OBJ_EDI_PARTY_NAME 10 -#define GN_OBJ_URI 12 -#define GN_OBJ_IP_ADDRESS 14 -#define GN_OBJ_REGISTERED_ID 16 -#define GN_OBJ_ROOF 18 - -/** - * ASN.1 definition of otherName - */ -static const asn1Object_t otherNameObjects[] = { - {0, "type-id", ASN1_OID, ASN1_BODY }, /* 0 */ - {0, "value", ASN1_CONTEXT_C_0, ASN1_BODY } /* 1 */ -}; -#define ON_OBJ_ID_TYPE 0 -#define ON_OBJ_VALUE 1 -#define ON_OBJ_ROOF 2 -/** - * ASN.1 definition of a basicConstraints extension - */ -static const asn1Object_t basicConstraintsObjects[] = { - { 0, "basicConstraints", ASN1_SEQUENCE, ASN1_NONE }, /* 0 */ - { 1, "CA", ASN1_BOOLEAN, ASN1_DEF|ASN1_BODY }, /* 1 */ - { 1, "pathLenConstraint", ASN1_INTEGER, ASN1_OPT|ASN1_BODY }, /* 2 */ - { 1, "end opt", ASN1_EOC, ASN1_END } /* 3 */ -}; -#define BASIC_CONSTRAINTS_CA 1 -#define BASIC_CONSTRAINTS_ROOF 4 - -/** - * ASN.1 definition of a keyIdentifier - */ -static const asn1Object_t keyIdentifierObjects[] = { - { 0, "keyIdentifier", ASN1_OCTET_STRING, ASN1_BODY } /* 0 */ -}; - -/** - * ASN.1 definition of a authorityKeyIdentifier extension - */ -static const asn1Object_t authorityKeyIdentifierObjects[] = { - { 0, "authorityKeyIdentifier", ASN1_SEQUENCE, ASN1_NONE }, /* 0 */ - { 1, "keyIdentifier", ASN1_CONTEXT_S_0, ASN1_OPT|ASN1_OBJ }, /* 1 */ - { 1, "end opt", ASN1_EOC, ASN1_END }, /* 2 */ - { 1, "authorityCertIssuer", ASN1_CONTEXT_C_1, ASN1_OPT|ASN1_OBJ }, /* 3 */ - { 1, "end opt", ASN1_EOC, ASN1_END }, /* 4 */ - { 1, "authorityCertSerialNumber",ASN1_CONTEXT_S_2, ASN1_OPT|ASN1_BODY }, /* 5 */ - { 1, "end opt", ASN1_EOC, ASN1_END } /* 6 */ -}; -#define AUTH_KEY_ID_KEY_ID 1 -#define AUTH_KEY_ID_CERT_ISSUER 3 -#define AUTH_KEY_ID_CERT_SERIAL 5 -#define AUTH_KEY_ID_ROOF 7 - -/** - * ASN.1 definition of a authorityInfoAccess extension - */ -static const asn1Object_t authorityInfoAccessObjects[] = { - { 0, "authorityInfoAccess", ASN1_SEQUENCE, ASN1_LOOP }, /* 0 */ - { 1, "accessDescription", ASN1_SEQUENCE, ASN1_NONE }, /* 1 */ - { 2, "accessMethod", ASN1_OID, ASN1_BODY }, /* 2 */ - { 2, "accessLocation", ASN1_EOC, ASN1_RAW }, /* 3 */ - { 0, "end loop", ASN1_EOC, ASN1_END } /* 4 */ -}; -#define AUTH_INFO_ACCESS_METHOD 2 -#define AUTH_INFO_ACCESS_LOCATION 3 -#define AUTH_INFO_ACCESS_ROOF 5 - -/** - * ASN.1 definition of a extendedKeyUsage extension - */ -static const asn1Object_t extendedKeyUsageObjects[] = { - { 0, "extendedKeyUsage", ASN1_SEQUENCE, ASN1_LOOP }, /* 0 */ - { 1, "keyPurposeID", ASN1_OID, ASN1_BODY }, /* 1 */ - { 0, "end loop", ASN1_EOC, ASN1_END }, /* 2 */ -}; - -#define EXT_KEY_USAGE_PURPOSE_ID 1 -#define EXT_KEY_USAGE_ROOF 3 - -/** - * ASN.1 definition of generalNames - */ -static const asn1Object_t generalNamesObjects[] = { - { 0, "generalNames", ASN1_SEQUENCE, ASN1_LOOP }, /* 0 */ - { 1, "generalName", ASN1_EOC, ASN1_RAW }, /* 1 */ - { 0, "end loop", ASN1_EOC, ASN1_END } /* 2 */ -}; -#define GENERAL_NAMES_GN 1 -#define GENERAL_NAMES_ROOF 3 - - -/** - * ASN.1 definition of crlDistributionPoints - */ -static const asn1Object_t crlDistributionPointsObjects[] = { - { 0, "crlDistributionPoints", ASN1_SEQUENCE, ASN1_LOOP }, /* 0 */ - { 1, "DistributionPoint", ASN1_SEQUENCE, ASN1_NONE }, /* 1 */ - { 2, "distributionPoint", ASN1_CONTEXT_C_0, ASN1_OPT|ASN1_LOOP }, /* 2 */ - { 3, "fullName", ASN1_CONTEXT_C_0, ASN1_OPT|ASN1_OBJ }, /* 3 */ - { 3, "end choice", ASN1_EOC, ASN1_END }, /* 4 */ - { 3, "nameRelToCRLIssuer",ASN1_CONTEXT_C_1, ASN1_OPT|ASN1_BODY }, /* 5 */ - { 3, "end choice", ASN1_EOC, ASN1_END }, /* 6 */ - { 2, "end opt", ASN1_EOC, ASN1_END }, /* 7 */ - { 2, "reasons", ASN1_CONTEXT_C_1, ASN1_OPT|ASN1_BODY }, /* 8 */ - { 2, "end opt", ASN1_EOC, ASN1_END }, /* 9 */ - { 2, "crlIssuer", ASN1_CONTEXT_C_2, ASN1_OPT|ASN1_BODY }, /* 10 */ - { 2, "end opt", ASN1_EOC, ASN1_END }, /* 11 */ - { 0, "end loop", ASN1_EOC, ASN1_END }, /* 12 */ -}; -#define CRL_DIST_POINTS_FULLNAME 3 -#define CRL_DIST_POINTS_ROOF 13 - -/** - * ASN.1 definition of an X.509v3 x509 - */ -static const asn1Object_t certObjects[] = { - { 0, "x509", ASN1_SEQUENCE, ASN1_OBJ }, /* 0 */ - { 1, "tbsCertificate", ASN1_SEQUENCE, ASN1_OBJ }, /* 1 */ - { 2, "DEFAULT v1", ASN1_CONTEXT_C_0, ASN1_DEF }, /* 2 */ - { 3, "version", ASN1_INTEGER, ASN1_BODY }, /* 3 */ - { 2, "serialNumber", ASN1_INTEGER, ASN1_BODY }, /* 4 */ - { 2, "signature", ASN1_EOC, ASN1_RAW }, /* 5 */ - { 2, "issuer", ASN1_SEQUENCE, ASN1_OBJ }, /* 6 */ - { 2, "validity", ASN1_SEQUENCE, ASN1_NONE }, /* 7 */ - { 3, "notBefore", ASN1_EOC, ASN1_RAW }, /* 8 */ - { 3, "notAfter", ASN1_EOC, ASN1_RAW }, /* 9 */ - { 2, "subject", ASN1_SEQUENCE, ASN1_OBJ }, /* 10 */ - { 2, "subjectPublicKeyInfo",ASN1_SEQUENCE, ASN1_NONE }, /* 11 */ - { 3, "algorithm", ASN1_EOC, ASN1_RAW }, /* 12 */ - { 3, "subjectPublicKey", ASN1_BIT_STRING, ASN1_NONE }, /* 13 */ - { 4, "RSAPublicKey", ASN1_SEQUENCE, ASN1_RAW }, /* 14 */ - { 2, "issuerUniqueID", ASN1_CONTEXT_C_1, ASN1_OPT }, /* 15 */ - { 2, "end opt", ASN1_EOC, ASN1_END }, /* 16 */ - { 2, "subjectUniqueID", ASN1_CONTEXT_C_2, ASN1_OPT }, /* 17 */ - { 2, "end opt", ASN1_EOC, ASN1_END }, /* 18 */ - { 2, "optional extensions", ASN1_CONTEXT_C_3, ASN1_OPT }, /* 19 */ - { 3, "extensions", ASN1_SEQUENCE, ASN1_LOOP }, /* 20 */ - { 4, "extension", ASN1_SEQUENCE, ASN1_NONE }, /* 21 */ - { 5, "extnID", ASN1_OID, ASN1_BODY }, /* 22 */ - { 5, "critical", ASN1_BOOLEAN, ASN1_DEF|ASN1_BODY }, /* 23 */ - { 5, "extnValue", ASN1_OCTET_STRING, ASN1_BODY }, /* 24 */ - { 3, "end loop", ASN1_EOC, ASN1_END }, /* 25 */ - { 2, "end opt", ASN1_EOC, ASN1_END }, /* 26 */ - { 1, "signatureAlgorithm", ASN1_EOC, ASN1_RAW }, /* 27 */ - { 1, "signatureValue", ASN1_BIT_STRING, ASN1_BODY } /* 28 */ -}; -#define X509_OBJ_CERTIFICATE 0 -#define X509_OBJ_TBS_CERTIFICATE 1 -#define X509_OBJ_VERSION 3 -#define X509_OBJ_SERIAL_NUMBER 4 -#define X509_OBJ_SIG_ALG 5 -#define X509_OBJ_ISSUER 6 -#define X509_OBJ_NOT_BEFORE 8 -#define X509_OBJ_NOT_AFTER 9 -#define X509_OBJ_SUBJECT 10 -#define X509_OBJ_SUBJECT_PUBLIC_KEY_ALGORITHM 12 -#define X509_OBJ_SUBJECT_PUBLIC_KEY 13 -#define X509_OBJ_RSA_PUBLIC_KEY 14 -#define X509_OBJ_EXTN_ID 22 -#define X509_OBJ_CRITICAL 23 -#define X509_OBJ_EXTN_VALUE 24 -#define X509_OBJ_ALGORITHM 27 -#define X509_OBJ_SIGNATURE 28 -#define X509_OBJ_ROOF 29 - - -static u_char ASN1_subjectAltName_oid_str[] = { - 0x06, 0x03, 0x55, 0x1D, 0x11 -}; - -static const chunk_t ASN1_subjectAltName_oid = chunk_from_buf(ASN1_subjectAltName_oid_str); - - -/** - * compare two X.509 x509s by comparing their signatures - */ -static bool equals(const private_x509_t *this, const private_x509_t *other) -{ - return chunk_equals(this->signature, other->signature); -} - -/** - * extracts the basicConstraints extension - */ -static bool parse_basicConstraints(chunk_t blob, int level0) -{ - asn1_ctx_t ctx; - chunk_t object; - u_int level; - int objectID = 0; - bool isCA = FALSE; - - asn1_init(&ctx, blob, level0, FALSE, FALSE); - - while (objectID < BASIC_CONSTRAINTS_ROOF) { - - if (!extract_object(basicConstraintsObjects, &objectID, &object,&level, &ctx)) - { - break; - } - if (objectID == BASIC_CONSTRAINTS_CA) - { - isCA = object.len && *object.ptr; - DBG2(" %s", isCA ? "TRUE" : "FALSE"); - } - objectID++; - } - return isCA; -} - -/** - * extracts an otherName - */ -static bool parse_otherName(chunk_t blob, int level0) -{ - asn1_ctx_t ctx; - chunk_t object; - u_int level; - int objectID = 0; - int oid = OID_UNKNOWN; - - asn1_init(&ctx, blob, level0, FALSE, FALSE); - - while (objectID < ON_OBJ_ROOF) - { - if (!extract_object(otherNameObjects, &objectID, &object, &level, &ctx)) - return FALSE; - - switch (objectID) - { - case ON_OBJ_ID_TYPE: - oid = known_oid(object); - break; - case ON_OBJ_VALUE: - if (oid == OID_XMPP_ADDR) - { - if (!parse_asn1_simple_object(&object, ASN1_UTF8STRING, level + 1, "xmppAddr")) - return FALSE; - } - break; - default: - break; - } - objectID++; - } - return TRUE; -} - -/** - * extracts a generalName - */ -static identification_t *parse_generalName(chunk_t blob, int level0) -{ - asn1_ctx_t ctx; - chunk_t object; - int objectID = 0; - u_int level; - - asn1_init(&ctx, blob, level0, FALSE, FALSE); - - while (objectID < GN_OBJ_ROOF) - { - id_type_t id_type = ID_ANY; - - if (!extract_object(generalNameObjects, &objectID, &object, &level, &ctx)) - return NULL; - - switch (objectID) - { - case GN_OBJ_RFC822_NAME: - id_type = ID_RFC822_ADDR; - break; - case GN_OBJ_DNS_NAME: - id_type = ID_FQDN; - break; - case GN_OBJ_URI: - id_type = ID_DER_ASN1_GN_URI; - break; - case GN_OBJ_DIRECTORY_NAME: - id_type = ID_DER_ASN1_DN; - break; - case GN_OBJ_IP_ADDRESS: - id_type = (object.len == 4)? ID_IPV4_ADDR : ID_IPV6_ADDR; - break; - case GN_OBJ_OTHER_NAME: - if (!parse_otherName(object, level + 1)) - return NULL; - break; - case GN_OBJ_X400_ADDRESS: - case GN_OBJ_EDI_PARTY_NAME: - case GN_OBJ_REGISTERED_ID: - break; - default: - break; - } - - if (id_type != ID_ANY) - { - identification_t *gn = identification_create_from_encoding(id_type, object); - DBG2(" '%D'", gn); - return gn; - } - objectID++; - } - return NULL; -} - - -/* - * Defined in header. - */ -void x509_parse_generalNames(chunk_t blob, int level0, bool implicit, linked_list_t *list) -{ - asn1_ctx_t ctx; - chunk_t object; - u_int level; - int objectID = 0; - - asn1_init(&ctx, blob, level0, implicit, FALSE); - - while (objectID < GENERAL_NAMES_ROOF) - { - if (!extract_object(generalNamesObjects, &objectID, &object, &level, &ctx)) - return; - - if (objectID == GENERAL_NAMES_GN) - { - identification_t *gn = parse_generalName(object, level+1); - - if (gn != NULL) - list->insert_last(list, (void *)gn); - } - objectID++; - } - return; -} - -/** - * extracts a keyIdentifier - */ -static chunk_t parse_keyIdentifier(chunk_t blob, int level0, bool implicit) -{ - asn1_ctx_t ctx; - chunk_t object; - u_int level; - int objectID = 0; - - asn1_init(&ctx, blob, level0, implicit, FALSE); - - extract_object(keyIdentifierObjects, &objectID, &object, &level, &ctx); - return object; -} - -/* - * Defined in header. - */ -void x509_parse_authorityKeyIdentifier(chunk_t blob, int level0 , chunk_t *authKeyID, chunk_t *authKeySerialNumber) -{ - asn1_ctx_t ctx; - chunk_t object; - u_int level; - int objectID = 0; - - *authKeyID = chunk_empty; - *authKeySerialNumber = chunk_empty; - - asn1_init(&ctx, blob, level0, FALSE, FALSE); - - while (objectID < AUTH_KEY_ID_ROOF) - { - if (!extract_object(authorityKeyIdentifierObjects, &objectID, &object, &level, &ctx)) - { - return; - } - switch (objectID) - { - case AUTH_KEY_ID_KEY_ID: - *authKeyID = parse_keyIdentifier(object, level+1, TRUE); - break; - case AUTH_KEY_ID_CERT_ISSUER: - { - /* TODO: parse_generalNames(object, level+1, TRUE); */ - break; - } - case AUTH_KEY_ID_CERT_SERIAL: - *authKeySerialNumber = object; - break; - default: - break; - } - objectID++; - } -} - -/** - * extracts an authorityInfoAcess location - */ -static void parse_authorityInfoAccess(chunk_t blob, int level0, linked_list_t *list) -{ - asn1_ctx_t ctx; - chunk_t object; - u_int level; - int objectID = 0; - int accessMethod = OID_UNKNOWN; - - asn1_init(&ctx, blob, level0, FALSE, FALSE); - while (objectID < AUTH_INFO_ACCESS_ROOF) - { - if (!extract_object(authorityInfoAccessObjects, &objectID, &object, &level, &ctx)) - { - return; - } - switch (objectID) - { - case AUTH_INFO_ACCESS_METHOD: - accessMethod = known_oid(object); - break; - case AUTH_INFO_ACCESS_LOCATION: - { - switch (accessMethod) - { - case OID_OCSP: - case OID_CA_ISSUERS: - { - identification_t *accessLocation; - - accessLocation = parse_generalName(object, level+1); - if (accessLocation == NULL) - { - /* parsing went wrong - abort */ - return; - } - DBG2(" '%D'", accessLocation); - if (accessMethod == OID_OCSP) - { - list->insert_last(list, (void *)accessLocation); - } - else - { - /* caIsssuer accessLocation is not used yet */ - accessLocation->destroy(accessLocation); - } - } - break; - default: - /* unkown accessMethod, ignoring */ - break; - } - break; - } - default: - break; - } - objectID++; - } -} - -/** - * extracts extendedKeyUsage OIDs - */ -static bool parse_extendedKeyUsage(chunk_t blob, int level0) -{ - asn1_ctx_t ctx; - chunk_t object; - u_int level; - int objectID = 0; - - asn1_init(&ctx, blob, level0, FALSE, FALSE); - while (objectID < EXT_KEY_USAGE_ROOF) - { - if (!extract_object(extendedKeyUsageObjects, &objectID, &object, &level, &ctx)) - { - return FALSE; - } - if (objectID == EXT_KEY_USAGE_PURPOSE_ID && - known_oid(object) == OID_OCSP_SIGNING) - { - return TRUE; - } - objectID++; - } - return FALSE; -} - -/** - * extracts one or several crlDistributionPoints and puts them into - * a chained list - */ -static void parse_crlDistributionPoints(chunk_t blob, int level0, linked_list_t *list) -{ - asn1_ctx_t ctx; - chunk_t object; - u_int level; - int objectID = 0; - - asn1_init(&ctx, blob, level0, FALSE, FALSE); - while (objectID < CRL_DIST_POINTS_ROOF) - { - if (!extract_object(crlDistributionPointsObjects, &objectID, &object, &level, &ctx)) - { - return; - } - if (objectID == CRL_DIST_POINTS_FULLNAME) - { - /* append extracted generalNames to existing chained list */ - x509_parse_generalNames(object, level+1, TRUE, list); - - } - objectID++; - } -} - - -/** - * Parses an X.509v3 certificate - */ -static bool parse_certificate(chunk_t blob, u_int level0, private_x509_t *this) -{ - asn1_ctx_t ctx; - bool critical; - chunk_t object; - u_int level; - int objectID = 0; - int extn_oid = OID_UNKNOWN; - - asn1_init(&ctx, blob, level0, FALSE, FALSE); - while (objectID < X509_OBJ_ROOF) - { - if (!extract_object(certObjects, &objectID, &object, &level, &ctx)) - { - return FALSE; - } - - /* those objects which will parsed further need the next higher level */ - level++; - - switch (objectID) - { - case X509_OBJ_CERTIFICATE: - this->certificate = object; - break; - case X509_OBJ_TBS_CERTIFICATE: - this->tbsCertificate = object; - break; - case X509_OBJ_VERSION: - this->version = (object.len) ? (1+(u_int)*object.ptr) : 1; - DBG2(" v%d", this->version); - break; - case X509_OBJ_SERIAL_NUMBER: - this->serialNumber = object; - break; - case X509_OBJ_SIG_ALG: - this->signatureAlgorithm = parse_algorithmIdentifier(object, level, NULL); - break; - case X509_OBJ_ISSUER: - this->issuer = identification_create_from_encoding(ID_DER_ASN1_DN, object); - DBG2(" '%D'", this->issuer); - break; - case X509_OBJ_NOT_BEFORE: - this->notBefore = parse_time(object, level); - break; - case X509_OBJ_NOT_AFTER: - this->notAfter = parse_time(object, level); - break; - case X509_OBJ_SUBJECT: - this->subject = identification_create_from_encoding(ID_DER_ASN1_DN, object); - DBG2(" '%D'", this->subject); - break; - case X509_OBJ_SUBJECT_PUBLIC_KEY_ALGORITHM: - if (parse_algorithmIdentifier(object, level, NULL) != OID_RSA_ENCRYPTION) - { - DBG1(" unsupported public key algorithm"); - return FALSE; - } - break; - case X509_OBJ_SUBJECT_PUBLIC_KEY: - if (ctx.blobs[4].len > 0 && *ctx.blobs[4].ptr == 0x00) - { - /* skip initial bit string octet defining 0 unused bits */ - ctx.blobs[4].ptr++; ctx.blobs[4].len--; - } - else - { - DBG1(" invalid RSA public key format"); - return FALSE; - } - break; - case X509_OBJ_RSA_PUBLIC_KEY: - this->subjectPublicKey = object; - break; - case X509_OBJ_EXTN_ID: - extn_oid = known_oid(object); - break; - case X509_OBJ_CRITICAL: - critical = object.len && *object.ptr; - DBG2(" %s", critical ? "TRUE" : "FALSE"); - break; - case X509_OBJ_EXTN_VALUE: - { - switch (extn_oid) - { - case OID_SUBJECT_KEY_ID: - this->subjectKeyID = chunk_clone(parse_keyIdentifier(object, level, FALSE)); - break; - case OID_SUBJECT_ALT_NAME: - x509_parse_generalNames(object, level, FALSE, this->subjectAltNames); - break; - case OID_BASIC_CONSTRAINTS: - this->isCA = parse_basicConstraints(object, level); - break; - case OID_CRL_DISTRIBUTION_POINTS: - parse_crlDistributionPoints(object, level, this->crlDistributionPoints); - break; - case OID_AUTHORITY_KEY_ID: - x509_parse_authorityKeyIdentifier(object, level, - &this->authKeyID, &this->authKeySerialNumber); - break; - case OID_AUTHORITY_INFO_ACCESS: - parse_authorityInfoAccess(object, level, this->ocspAccessLocations); - break; - case OID_EXTENDED_KEY_USAGE: - this->isOcspSigner = parse_extendedKeyUsage(object, level); - break; - case OID_NS_REVOCATION_URL: - case OID_NS_CA_REVOCATION_URL: - case OID_NS_CA_POLICY_URL: - case OID_NS_COMMENT: - if (!parse_asn1_simple_object(&object, ASN1_IA5STRING , level, oid_names[extn_oid].name)) - return FALSE; - break; - default: - break; - } - break; - } - case X509_OBJ_ALGORITHM: - { - int alg = parse_algorithmIdentifier(object, level, NULL); - - if (alg != this->signatureAlgorithm) - { - DBG1(" signature algorithms do not agree"); - return FALSE; - } - } - break; - case X509_OBJ_SIGNATURE: - this->signature = object; - break; - default: - break; - } - objectID++; - } - - /* generate the subjectKeyID if it is missing in the certificate */ - if (this->subjectKeyID.ptr == NULL) - { - hasher_t *hasher = hasher_create(HASH_SHA1); - - hasher->allocate_hash(hasher, this->subjectPublicKey, &this->subjectKeyID); - hasher->destroy(hasher); - } - - this->installed = time(NULL); - return TRUE; -} - -/** - * Implements x509_t.is_valid - */ -static err_t is_valid(const private_x509_t *this, time_t *until) -{ - time_t current_time = time(NULL); - - DBG2(" not before : %T", &this->notBefore); - DBG2(" current time: %T", ¤t_time); - DBG2(" not after : %T", &this->notAfter); - - if (until != NULL && - (*until == UNDEFINED_TIME || this->notAfter < *until)) - { - *until = this->notAfter; - } - if (current_time < this->notBefore) - { - return "is not valid yet"; - } - if (current_time > this->notAfter) - { - return "has expired"; - } - DBG2(" certificate is valid"); - return NULL; -} - -/** - * Implements x509_t.is_ca - */ -static bool is_ca(const private_x509_t *this) -{ - return this->isCA; -} - -/** - * Implements x509_t.is_ocsp_signer - */ -static bool is_ocsp_signer(const private_x509_t *this) -{ - return this->isOcspSigner; -} - -/** - * Implements x509_t.is_self_signed - */ -static bool is_self_signed(const private_x509_t *this) -{ - return this->isSelfSigned; -} - -/** - * Implements x509_t.equals_subjectAltName - */ -static bool equals_subjectAltName(const private_x509_t *this, identification_t *id) -{ - bool found = FALSE; - identification_t *subjectAltName; - iterator_t *iterator; - - iterator = this->subjectAltNames->create_iterator(this->subjectAltNames, TRUE); - while (iterator->iterate(iterator, (void**)&subjectAltName)) - { - if (id->equals(id, subjectAltName)) - { - found = TRUE; - break; - } - } - iterator->destroy(iterator); - return found; -} - -/** - * Implements x509_t.is_issuer - */ -static bool is_issuer(const private_x509_t *this, const private_x509_t *issuer) -{ - return (this->authKeyID.ptr) - ? chunk_equals(this->authKeyID, issuer->subjectKeyID) - : (this->issuer->equals(this->issuer, issuer->subject) - && chunk_equals_or_null(this->authKeySerialNumber, issuer->serialNumber)); -} - -/** - * Implements x509_t.get_certificate - */ -static chunk_t get_certificate(const private_x509_t *this) -{ - return this->certificate; -} - -/** - * Implements x509_t.get_public_key - */ -static rsa_public_key_t *get_public_key(const private_x509_t *this) -{ - return this->public_key; -} - -/** - * Implements x509_t.get_serialNumber - */ -static chunk_t get_serialNumber(const private_x509_t *this) -{ - return this->serialNumber; -} - -/** - * Implements x509_t.get_subjectKeyID - */ -static chunk_t get_subjectKeyID(const private_x509_t *this) -{ - return this->subjectKeyID; -} - -/** - * Implements x509_t.get_keyid - */ -static chunk_t get_keyid(const private_x509_t *this) -{ - return this->public_key->get_keyid(this->public_key); -} - -/** - * Implements x509_t.get_issuer - */ -static identification_t *get_issuer(const private_x509_t *this) -{ - return this->issuer; -} - -/** - * Implements x509_t.get_subject - */ -static identification_t *get_subject(const private_x509_t *this) -{ - return this->subject; -} - -/** - * Implements x509_t.set_ca_info - */ -static void set_ca_info(private_x509_t *this, ca_info_t *ca_info) -{ - this->ca_info = ca_info; -} - -/** - * Implements x509_t.get_ca_info - */ -static ca_info_t *get_ca_info(const private_x509_t *this) -{ - return this->ca_info; -} - -/** - * Implements x509_t.set_until - */ -static void set_until(private_x509_t *this, time_t until) -{ - this->until = until; -} - -/** - * Implements x509_t.get_until - */ -static time_t get_until(const private_x509_t *this) -{ - return this->until; -} - -/** - * Implements x509_t.set_status - */ -static void set_status(private_x509_t *this, cert_status_t status) -{ - this->status = status; -} - -/** - * Implements x509_t.get_status - */ -static cert_status_t get_status(const private_x509_t *this) -{ - return this->status; -} - -/** - * Implements x509_t.add_authority_flags - */ -static void add_authority_flags(private_x509_t *this, u_int flags) -{ - this->authority_flags |= flags; -} - -/** - * Implements x509_t.add_authority_flags - */ -static u_int get_authority_flags(private_x509_t *this) -{ - return this->authority_flags; -} - -/** - * Implements x509_t.has_authority_flag - */ -static bool has_authority_flag(private_x509_t *this, u_int flags) -{ - return (this->authority_flags & flags) != AUTH_NONE; -} - -/** - * Implements x509_t.create_crluri_iterator - */ -static iterator_t *create_crluri_iterator(const private_x509_t *this) -{ - return this->crlDistributionPoints->create_iterator(this->crlDistributionPoints, TRUE); -} - -/** - * Implements x509_t.create_crluri_iterator - */ -static iterator_t *create_ocspuri_iterator(const private_x509_t *this) -{ - return this->ocspAccessLocations->create_iterator(this->ocspAccessLocations, TRUE); -} - -/** - * Implements x509_t.verify - */ -static bool verify(const private_x509_t *this, const rsa_public_key_t *signer) -{ - hash_algorithm_t algorithm = hasher_algorithm_from_oid(this->signatureAlgorithm); - - if (algorithm == HASH_UNKNOWN) - { - DBG1(" unknown signature algorithm"); - return FALSE; - } - return signer->verify_emsa_pkcs1_signature(signer, algorithm, this->tbsCertificate, this->signature) == SUCCESS; -} - -/** - * Implementation of x509_t.list. - */ -static void list(private_x509_t *this, FILE *out, bool utc) -{ - iterator_t *iterator; - time_t now = time(NULL); - - fprintf(out, "%#T\n", &this->installed, utc); - - if (this->subjectAltNames->get_count(this->subjectAltNames)) - { - identification_t *subjectAltName; - bool first = TRUE; - - fprintf(out, " altNames: "); - iterator = this->subjectAltNames->create_iterator(this->subjectAltNames, TRUE); - while (iterator->iterate(iterator, (void**)&subjectAltName)) - { - if (first) - { - first = FALSE; - } - else - { - fprintf(out, ", "); - } - fprintf(out, "'%D'", subjectAltName); - } - iterator->destroy(iterator); - fprintf(out, "\n"); - } - fprintf(out, " subject: '%D'\n", this->subject); - fprintf(out, " issuer: '%D'\n", this->issuer); - fprintf(out, " serial: %#B\n", &this->serialNumber); - fprintf(out, " validity: not before %#T, ", &this->notBefore, utc); - if (now < this->notBefore) - { - fprintf(out, "not valid yet (valid in %#V)\n", &now, &this->notBefore); - } - else - { - fprintf(out, "ok\n"); - } - - fprintf(out, " not after %#T, ", &this->notAfter, utc); - if (now > this->notAfter) - { - fprintf(out, "expired (%#V ago)\n", &now, &this->notAfter); - } - else - { - fprintf(out, "ok"); - if (now > this->notAfter - CERT_WARNING_INTERVAL * 60 * 60 * 24) - { - fprintf(out, " (expires in %#V)", &now, &this->notAfter); - } - fprintf(out, " \n"); - } - - { - chunk_t keyid = this->public_key->get_keyid(this->public_key); - fprintf(out, " keyid: %#B\n", &keyid); - } - - if (this->subjectKeyID.ptr) - { - fprintf(out, " subjkey: %#B\n", &this->subjectKeyID); - } - if (this->authKeyID.ptr) - { - fprintf(out, " authkey: %#B\n", &this->authKeyID); - } - if (this->authKeySerialNumber.ptr) - { - fprintf(out, " aserial: %#B\n", &this->authKeySerialNumber); - } - - fprintf(out, " pubkey: RSA %d bits", BITS_PER_BYTE * - this->public_key->get_keysize(this->public_key)); - fprintf(out, ", status %N", - cert_status_names, this->status); - - switch (this->status) - { - case CERT_GOOD: - fprintf(out, " until %#T", &this->until, utc); - break; - case CERT_REVOKED: - fprintf(out, " on %#T", &this->until, utc); - break; - case CERT_UNKNOWN: - case CERT_UNDEFINED: - case CERT_UNTRUSTED: - default: - break; - } -} - -/** - * Implements x509_t.add_subjectAltNames. - */ -static void add_subjectAltNames(private_x509_t *this, linked_list_t *subjectAltNames) -{ - iterator_t *iterator = subjectAltNames->create_iterator(subjectAltNames, TRUE); - identification_t *name = NULL; - - while (iterator->iterate(iterator, (void**)&name)) - { - name = name->clone(name); - this->subjectAltNames->insert_last(this->subjectAltNames, (void*)name); - } - iterator->destroy(iterator); -} - -/* - * Defined in header. - */ -chunk_t x509_build_generalNames(linked_list_t *list) -{ - linked_list_t *generalNames = linked_list_create(); - iterator_t *iterator = list->create_iterator(list, TRUE); - identification_t *name; - chunk_t names = chunk_empty; - size_t len = 0; - - while (iterator->iterate(iterator, (void**)&name)) - { - asn1_t asn1_type = ASN1_EOC; - chunk_t *generalName; - - switch (name->get_type(name)) - { - case ID_RFC822_ADDR: - asn1_type = ASN1_CONTEXT_S_1; - break; - case ID_FQDN: - asn1_type = ASN1_CONTEXT_S_2; - break; - case ID_DER_ASN1_DN: - asn1_type = ASN1_CONTEXT_C_4; - break; - case ID_DER_ASN1_GN_URI: - asn1_type = ASN1_CONTEXT_S_6; - break; - case ID_IPV4_ADDR: - case ID_IPV6_ADDR: - asn1_type = ASN1_CONTEXT_S_7; - break; - default: - continue; - } - - generalName = malloc_thing(chunk_t); - *generalName = asn1_simple_object(asn1_type, name->get_encoding(name)); - len += generalName->len; - generalNames->insert_last(generalNames, (void*)generalName); - } - iterator->destroy(iterator); - - if (len > 0) - { - iterator_t *iterator = generalNames->create_iterator(generalNames, TRUE); - chunk_t *generalName; - u_char *pos = build_asn1_object(&names, ASN1_SEQUENCE, len); - - while (iterator->iterate(iterator, (void**)&generalName)) - { - memcpy(pos, generalName->ptr, generalName->len); - pos += generalName->len; - free(generalName->ptr); - free(generalName); - } - iterator->destroy(iterator); - } - generalNames->destroy(generalNames); - return names; -} - -/* - * Defined in header. - */ -chunk_t x509_build_subjectAltNames(linked_list_t *list) -{ - chunk_t generalNames = x509_build_generalNames(list); - - if (generalNames.len) - { - return asn1_wrap(ASN1_SEQUENCE, "cm", - ASN1_subjectAltName_oid, - asn1_wrap(ASN1_OCTET_STRING, "m", generalNames) - ); - } - else - { - return chunk_empty; - } -} - -/** - * Build a to-be-signed X.509 certificate body - */ -static chunk_t x509_build_tbs(private_x509_t *this) -{ - /* version is always X.509v3 */ - chunk_t version = asn1_simple_object(ASN1_CONTEXT_C_0, ASN1_INTEGER_2); - - chunk_t extensions = chunk_empty; - - if (this->subjectAltNames->get_count(this->subjectAltNames)) - { - extensions = asn1_wrap(ASN1_CONTEXT_C_3, "m", - asn1_wrap(ASN1_SEQUENCE, "m", - x509_build_subjectAltNames(this->subjectAltNames))); - } - - return asn1_wrap(ASN1_SEQUENCE, "mmccmcmm", - version, - asn1_simple_object(ASN1_INTEGER, this->serialNumber), - asn1_algorithmIdentifier(this->signatureAlgorithm), - this->issuer->get_encoding(this->issuer), - asn1_wrap(ASN1_SEQUENCE, "mm", - timetoasn1(&this->notBefore, ASN1_UTCTIME), - timetoasn1(&this->notAfter, ASN1_UTCTIME) - ), - this->subject->get_encoding(this->subject), - this->public_key->get_publicKeyInfo(this->public_key), - extensions - ); -} - -/** - * Implementation of x509_t.build_encoding. - */ -static void build_encoding(private_x509_t *this, hash_algorithm_t alg, - rsa_private_key_t *private_key) -{ - chunk_t signature; - - this->signatureAlgorithm = hasher_signature_algorithm_to_oid(alg); - this->tbsCertificate = x509_build_tbs(this); - private_key->build_emsa_pkcs1_signature(private_key, alg, - this->tbsCertificate, &signature); - this->signature = asn1_bitstring("m", signature); - this->certificate = asn1_wrap(ASN1_SEQUENCE, "mcm", - this->tbsCertificate, - asn1_algorithmIdentifier(this->signatureAlgorithm), - this->signature); - -} - -/** - * Implements x509_t.destroy - */ -static void destroy(private_x509_t *this) -{ - this->subjectAltNames->destroy_offset(this->subjectAltNames, - offsetof(identification_t, destroy)); - this->crlDistributionPoints->destroy_offset(this->crlDistributionPoints, - offsetof(identification_t, destroy)); - this->ocspAccessLocations->destroy_offset(this->ocspAccessLocations, - offsetof(identification_t, destroy)); - DESTROY_IF(this->issuer); - DESTROY_IF(this->subject); - DESTROY_IF(this->public_key); - free(this->subjectKeyID.ptr); - free(this->certificate.ptr); - free(this); -} - -/** - * Internal generic constructor - */ -static private_x509_t *x509_create_empty(void) -{ - private_x509_t *this = malloc_thing(private_x509_t); - - /* initialize */ - this->subjectPublicKey = chunk_empty; - this->public_key = NULL; - this->subject = NULL; - this->issuer = NULL; - this->ca_info = NULL; - this->subjectAltNames = linked_list_create(); - this->crlDistributionPoints = linked_list_create(); - this->ocspAccessLocations = linked_list_create(); - this->subjectKeyID = chunk_empty; - this->authKeyID = chunk_empty; - this->authKeySerialNumber = chunk_empty; - this->authority_flags = AUTH_NONE; - this->isCA = FALSE; - this->isOcspSigner = FALSE; - - /* public functions */ - this->public.equals = (bool (*) (const x509_t*,const x509_t*))equals; - this->public.equals_subjectAltName = (bool (*) (const x509_t*,identification_t*))equals_subjectAltName; - this->public.is_issuer = (bool (*) (const x509_t*,const x509_t*))is_issuer; - this->public.is_valid = (err_t (*) (const x509_t*,time_t*))is_valid; - this->public.is_ca = (bool (*) (const x509_t*))is_ca; - this->public.is_self_signed = (bool (*) (const x509_t*))is_self_signed; - this->public.is_ocsp_signer = (bool (*) (const x509_t*))is_ocsp_signer; - this->public.get_certificate = (chunk_t (*) (const x509_t*))get_certificate; - this->public.get_public_key = (rsa_public_key_t* (*) (const x509_t*))get_public_key; - this->public.get_serialNumber = (chunk_t (*) (const x509_t*))get_serialNumber; - this->public.get_subjectKeyID = (chunk_t (*) (const x509_t*))get_subjectKeyID; - this->public.get_keyid = (chunk_t (*) (const x509_t*))get_keyid; - this->public.get_issuer = (identification_t* (*) (const x509_t*))get_issuer; - this->public.get_subject = (identification_t* (*) (const x509_t*))get_subject; - this->public.set_ca_info = (void (*) (x509_t*,ca_info_t*))set_ca_info; - this->public.get_ca_info = (ca_info_t* (*) (const x509_t*))get_ca_info; - this->public.set_until = (void (*) (x509_t*,time_t))set_until; - this->public.get_until = (time_t (*) (const x509_t*))get_until; - this->public.set_status = (void (*) (x509_t*,cert_status_t))set_status; - this->public.get_status = (cert_status_t (*) (const x509_t*))get_status; - this->public.add_authority_flags = (void (*) (x509_t*,u_int))add_authority_flags; - this->public.get_authority_flags = (u_int (*) (x509_t*))get_authority_flags; - this->public.has_authority_flag = (bool (*) (x509_t*,u_int))has_authority_flag; - this->public.create_crluri_iterator = (iterator_t* (*) (const x509_t*))create_crluri_iterator; - this->public.create_ocspuri_iterator = (iterator_t* (*) (const x509_t*))create_ocspuri_iterator; - this->public.verify = (bool (*) (const x509_t*,const rsa_public_key_t*))verify; - this->public.list = (void (*) (x509_t*, FILE *out, bool utc))list; - this->public.add_subjectAltNames = (void (*) (x509_t*,linked_list_t*))add_subjectAltNames; - this->public.build_encoding = (void (*) (x509_t*,hash_algorithm_t,rsa_private_key_t*))build_encoding; - this->public.destroy = (void (*) (x509_t*))destroy; - - return this; -} - -/* - * Described in header. - */ -x509_t *x509_create(chunk_t serialNumber, identification_t *issuer, - time_t notBefore, time_t notAfter, - identification_t *subject, - rsa_public_key_t *public_key) -{ - private_x509_t *this = x509_create_empty(); - - this->serialNumber = serialNumber; - this->issuer = issuer->clone(issuer); - this->notBefore = notBefore; - this->notAfter = notAfter; - this->subject = subject->clone(subject); - this->public_key = public_key->clone(public_key); - - return &this->public; -} - -/* - * Described in header. - */ -x509_t *x509_create_from_chunk(chunk_t chunk, u_int level) -{ - private_x509_t *this = x509_create_empty(); - - if (!parse_certificate(chunk, level, this)) - { - destroy(this); - return NULL; - } - - /* extract public key from certificate */ - this->public_key = rsa_public_key_create_from_chunk(this->subjectPublicKey); - if (this->public_key == NULL) - { - destroy(this); - return NULL; - } - - /* set trusted lifetime of public key to notAfter */ - this->until = this->notAfter; - - /* check if the certificate is self-signed */ - this->isSelfSigned = FALSE; - if (this->subject->equals(this->subject, this->issuer)) - { - hash_algorithm_t algorithm = hasher_algorithm_from_oid(this->signatureAlgorithm); - - if (algorithm == HASH_UNKNOWN) - { - destroy(this); - return NULL; - } - this->isSelfSigned = this->public_key->verify_emsa_pkcs1_signature(this->public_key, - algorithm, this->tbsCertificate, this->signature) == SUCCESS; - } - if (this->isSelfSigned) - { - DBG2(" certificate is self-signed"); - this->status = CERT_GOOD; - } - else - { - this->status = CERT_UNDEFINED; - } - - return &this->public; -} - -/* - * Described in header. - */ -x509_t *x509_create_from_file(const char *filename, const char *label) -{ - bool pgp = FALSE; - chunk_t chunk = chunk_empty; - char cert_label[BUF_LEN]; - - snprintf(cert_label, BUF_LEN, "%s certificate", label); - - if (!pem_asn1_load_file(filename, NULL, cert_label, &chunk, &pgp)) - { - return NULL; - } - return x509_create_from_chunk(chunk, 0); -} diff --git a/src/libstrongswan/crypto/x509.h b/src/libstrongswan/crypto/x509.h deleted file mode 100755 index def45be6b..000000000 --- a/src/libstrongswan/crypto/x509.h +++ /dev/null @@ -1,406 +0,0 @@ -/** - * @file x509.h - * - * @brief Interface of x509_t. - * - */ - -/* - * Copyright (C) 2000 Andreas Hess, Patric Lichtsteiner, Roger Wegmann - * Copyright (C) 2001 Marco Bertossa, Andreas Schleiss - * Copyright (C) 2002 Mario Strasser - * Copyright (C) 2006 Martin Willi - * Copyright (C) 2000-2008 Andreas Steffen - * - * Hochschule fuer Technik Rapperswil - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * RCSID $Id: x509.h 3421 2008-01-22 01:09:19Z andreas $ - */ - -#ifndef X509_H_ -#define X509_H_ - -typedef struct x509_t x509_t; - -#include <library.h> -#include <crypto/rsa/rsa_private_key.h> -#include <crypto/hashers/hasher.h> -#include <crypto/certinfo.h> -#include <crypto/ca.h> -#include <utils/identification.h> -#include <utils/iterator.h> -#include <utils/linked_list.h> - -/* authority flags */ - -#define AUTH_NONE 0x00 /* no authorities */ -#define AUTH_CA 0x01 /* certification authority */ -#define AUTH_AA 0x02 /* authorization authority */ -#define AUTH_OCSP 0x04 /* ocsp signing authority */ - -/** - * @brief X.509 certificate. - * - * @b Constructors: - * - x509_create() - * - x509_create_from_chunk() - * - x509_create_from_file() - * - * @ingroup crypto - */ -struct x509_t { - - /** - * @brief Set trusted public key life. - * - * @param this calling object - * @param until time until public key is trusted - */ - void (*set_until) (x509_t *this, time_t until); - - /** - * @brief Get trusted public key life. - * - * @param this calling object - * @return time until public key is trusted - */ - time_t (*get_until) (const x509_t *this); - - /** - * @brief Set the certificate status - * - * @param this calling object - * @param status certificate status - */ - void (*set_status) (x509_t *this, cert_status_t status); - - /** - * @brief Get the certificate status - * - * @param this calling object - * @return certificate status - */ - cert_status_t (*get_status) (const x509_t *this); - - /** - * @brief Add authority flags - * - * @param this calling object - * @param flag flags to be added - */ - void (*add_authority_flags) (x509_t *this, u_int flags); - - /** - * @brief Get authority flags - * - * @param this calling object - * @return authority flags - */ - u_int (*get_authority_flags) (x509_t *this); - - /** - * @brief Check a specific authority flag - * - * @param this calling object - * @param flag flag to be checked - * @return TRUE if flag is present - */ - bool (*has_authority_flag) (x509_t *this, u_int flag); - - /** - * @brief Get the DER-encoded X.509 certificate body - * - * @param this calling object - * @return DER-encoded X.509 certificate - */ - chunk_t (*get_certificate) (const x509_t *this); - - /** - * @brief Get the RSA public key from the certificate. - * - * @param this calling object - * @return public_key - */ - rsa_public_key_t *(*get_public_key) (const x509_t *this); - - /** - * @brief Get serial number from the certificate. - * - * @param this calling object - * @return serialNumber - */ - chunk_t (*get_serialNumber) (const x509_t *this); - - /** - * @brief Get subjectKeyID from the certificate. - * - * @param this calling object - * @return subjectKeyID - */ - chunk_t (*get_subjectKeyID) (const x509_t *this); - - /** - * @brief Get keyid from the certificate's public key. - * - * @param this calling object - * @return keyid - */ - chunk_t (*get_keyid) (const x509_t *this); - - /** - * @brief Get the issuerDistinguishedName - * - * The resulting ID is always a identification_t - * of type ID_DER_ASN1_DN. - * - * @param this calling object - * @return issuers ID - */ - identification_t *(*get_issuer) (const x509_t *this); - - /** - * @brief Get the subjectDistinguishedName. - * - * The resulting ID is always a identification_t - * of type ID_DER_ASN1_DN. - * - * @param this calling object - * @return subjects ID - */ - identification_t *(*get_subject) (const x509_t *this); - - /** - * @brief Set a link ca info - * - * @param this calling object - * @param ca_info link to the info record of the issuing ca - */ - void (*set_ca_info) (x509_t *this, ca_info_t *ca_info); - - /** - * @brief Get the . - * - * The resulting ID is always a identification_t - * of type ID_DER_ASN1_DN. - * - * @param this calling object - * @return link to the info record of the issuing ca - * or NULL if it does not [yet] exist - */ - ca_info_t *(*get_ca_info) (const x509_t *this); - - /** - * @brief Create an iterator for the crlDistributionPoints. - * - * @param this calling object - * @return iterator for crlDistributionPoints - */ - iterator_t *(*create_crluri_iterator) (const x509_t *this); - - /** - * @brief Create an iterator for the ocspAccessLocations. - * - * @param this calling object - * @return iterator for ocspAccessLocations - */ - iterator_t *(*create_ocspuri_iterator) (const x509_t *this); - - /** - * @brief Check if a certificate is trustworthy - * - * @param this calling object - * @param signer signer's RSA public key - */ - bool (*verify) (const x509_t *this, const rsa_public_key_t *signer); - - /** - * @brief Compare two certificates. - * - * Comparison is done via the certificates signature. - * - * @param this first cert for compare - * @param other second cert for compare - * @return TRUE if signature is equal - */ - bool (*equals) (const x509_t *this, const x509_t *that); - - /** - * @brief Checks if the certificate contains a subjectAltName equal to id. - * - * @param this certificate being examined - * @param id id which is being compared to the subjectAltNames - * @return TRUE if a match is found - */ - bool (*equals_subjectAltName) (const x509_t *this, identification_t *id); - - /** - * @brief Checks if the subject of the other cert is the issuer of this cert. - * - * @param this certificate - * @param issuer potential issuer certificate - * @return TRUE if issuer is found - */ - bool (*is_issuer) (const x509_t *this, const x509_t *issuer); - - /** - * @brief Checks the validity interval of the certificate - * - * @param this certificate being examined - * @param until until = min(until, notAfter) - * @return NULL if the certificate is valid - */ - err_t (*is_valid) (const x509_t *this, time_t *until); - - /** - * @brief Returns the CA basic constraints flag - * - * @param this certificate being examined - * @return TRUE if the CA flag is set - */ - bool (*is_ca) (const x509_t *this); - - /** - * @brief Returns the OCSPSigner extended key usage flag - * - * @param this certificate being examined - * @return TRUE if the OCSPSigner flag is set - */ - bool (*is_ocsp_signer) (const x509_t *this); - - /** - * @brief Checks if the certificate is self-signed (subject equals issuer) - * - * @param this certificate being examined - * @return TRUE if self-signed - */ - bool (*is_self_signed) (const x509_t *this); - - /** - * @brief Log the certificate info to out. - * - * @param this calling object - * @param out stream to write to - * @param utc TRUE for UTC times, FALSE for local time - */ - void (*list) (x509_t *this, FILE *out, bool utc); - - /** - * @brief Adds a list of subjectAltNames - * - * @param this calling object - * @param subjectAltNames list of subjectAltNames to be added - */ - void (*add_subjectAltNames) (x509_t *this, linked_list_t *subjectAltNames); - - /** - * @brief Builds a DER-encoded signed X.509 certificate - * - * @param this calling object - * @param alg hash algorithm used to compute the certificate digest - * @param private_key RSA private key used to sign the certificate digest - */ - void (*build_encoding) (x509_t *this, hash_algorithm_t alg, rsa_private_key_t *private_key); - - /** - * @brief Destroys the certificate. - * - * @param this certificate to destroy - */ - void (*destroy) (x509_t *this); -}; - -/** - * @brief Create a X.509 certificate from its components - * - * @param serialNumber chunk containing the serialNumber - * @param issuer issuer distinguished name - * @param notBefore start date of validity - * @param notAfter end date of validity - * @param subject subject distinguished name - * @param public_key public key - * - * @return created x509_t certificate, or NULL if invalid. - * - * @ingroup crypto - */ -x509_t *x509_create(chunk_t serialNumber, identification_t *issuer, - time_t notBefore, time_t notAfter, - identification_t *subject, - rsa_public_key_t *public_key); - -/** - * @brief Read a X.509 certificate from a DER encoded blob. - * - * @param chunk chunk containing DER encoded data - * @return created x509_t certificate, or NULL if invalid. - * - * @ingroup crypto - */ -x509_t *x509_create_from_chunk(chunk_t chunk, u_int level); - -/** - * @brief Read a X.509 certificate from a DER encoded file. - * - * @param filename file containing DER encoded data - * @param label label describing kind of certificate - * @return created x509_t certificate, or NULL if invalid. - * - * @ingroup crypto - */ -x509_t *x509_create_from_file(const char *filename, const char *label); - -/** - * @brief Parses a DER encoded authorityKeyIdentifier - * - * @param blob blob containing DER encoded data - * @param level0 indicates the current parsing level - * @param authKeyID assigns the authorityKeyIdentifier - * @param authKeySerialNumber assigns the authKeySerialNumber - * - * @ingroup crypto - */ -void x509_parse_authorityKeyIdentifier(chunk_t blob, int level0, chunk_t *authKeyID, chunk_t *authKeySerialNumber); - -/** - * @brief Parses DER encoded generalNames - * - * @param blob blob containing DER encoded data - * @param level0 indicates the current parsing level - * @param implicit implicit coding is used - * @param list list of decoded generalNames - * - * @ingroup crypto - */ -void x509_parse_generalNames(chunk_t blob, int level0, bool implicit, linked_list_t *list); - -/** - * @brief Builds a DER encoded list of generalNames - * - * @param list list of generalNames to be encoded - * @return DER encoded list of generalNames - * - * @ingroup crypto - */ -chunk_t x509_build_generalNames(linked_list_t *list); - -/** - * @brief Builds a DER encoded list of subjectAltNames - * - * @param list list of subjectAltNames to be encoded - * @return DER encoded list of subjectAltNames - * - * @ingroup crypto - */ -chunk_t x509_build_subjectAltNames(linked_list_t *list); - -#endif /* X509_H_ */ |