Annotation of embedaddon/strongswan/src/libstrongswan/plugins/openssl/openssl_util.c, revision 1.1
1.1 ! misho 1: /*
! 2: * Copyright (C) 2009 Martin Willi
! 3: * Copyright (C) 2008 Tobias Brunner
! 4: * HSR Hochschule fuer Technik Rapperswil
! 5: *
! 6: * This program is free software; you can redistribute it and/or modify it
! 7: * under the terms of the GNU General Public License as published by the
! 8: * Free Software Foundation; either version 2 of the License, or (at your
! 9: * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
! 10: *
! 11: * This program is distributed in the hope that it will be useful, but
! 12: * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
! 13: * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
! 14: * for more details.
! 15: */
! 16:
! 17: #include "openssl_util.h"
! 18:
! 19: #include <utils/debug.h>
! 20:
! 21: #include <openssl/bn.h>
! 22: #include <openssl/evp.h>
! 23: #include <openssl/x509.h>
! 24:
! 25: /* these were added with 1.1.0 when ASN1_OBJECT was made opaque */
! 26: #if OPENSSL_VERSION_NUMBER < 0x10100000L
! 27: #define OBJ_get0_data(o) ((o)->data)
! 28: #define OBJ_length(o) ((o)->length)
! 29: #define ASN1_STRING_get0_data(a) ASN1_STRING_data((ASN1_STRING*)a)
! 30: #endif
! 31:
! 32: /**
! 33: * Described in header.
! 34: */
! 35: bool openssl_hash_chunk(int hash_type, chunk_t data, chunk_t *hash)
! 36: {
! 37: EVP_MD_CTX *ctx;
! 38: bool ret = FALSE;
! 39: const EVP_MD *hasher = EVP_get_digestbynid(hash_type);
! 40: if (!hasher)
! 41: {
! 42: return FALSE;
! 43: }
! 44:
! 45: ctx = EVP_MD_CTX_create();
! 46: if (!ctx)
! 47: {
! 48: goto error;
! 49: }
! 50:
! 51: if (!EVP_DigestInit_ex(ctx, hasher, NULL))
! 52: {
! 53: goto error;
! 54: }
! 55:
! 56: if (!EVP_DigestUpdate(ctx, data.ptr, data.len))
! 57: {
! 58: goto error;
! 59: }
! 60:
! 61: *hash = chunk_alloc(EVP_MD_size(hasher));
! 62: if (!EVP_DigestFinal_ex(ctx, hash->ptr, NULL))
! 63: {
! 64: chunk_free(hash);
! 65: goto error;
! 66: }
! 67:
! 68: ret = TRUE;
! 69: error:
! 70: if (ctx)
! 71: {
! 72: EVP_MD_CTX_destroy(ctx);
! 73: }
! 74: return ret;
! 75: }
! 76:
! 77: /**
! 78: * Described in header.
! 79: */
! 80: bool openssl_bn_cat(const int len, const BIGNUM *a, const BIGNUM *b,
! 81: chunk_t *chunk)
! 82: {
! 83: int offset;
! 84:
! 85: chunk->len = len + (b ? len : 0);
! 86: chunk->ptr = malloc(chunk->len);
! 87: memset(chunk->ptr, 0, chunk->len);
! 88:
! 89: /* convert a */
! 90: offset = len - BN_num_bytes(a);
! 91: if (!BN_bn2bin(a, chunk->ptr + offset))
! 92: {
! 93: goto error;
! 94: }
! 95:
! 96: /* optionally convert and concatenate b */
! 97: if (b)
! 98: {
! 99: offset = len - BN_num_bytes(b);
! 100: if (!BN_bn2bin(b, chunk->ptr + len + offset))
! 101: {
! 102: goto error;
! 103: }
! 104: }
! 105:
! 106: return TRUE;
! 107: error:
! 108: chunk_free(chunk);
! 109: return FALSE;
! 110: }
! 111:
! 112: /**
! 113: * Described in header.
! 114: */
! 115: bool openssl_bn_split(chunk_t chunk, BIGNUM *a, BIGNUM *b)
! 116: {
! 117: int len;
! 118:
! 119: if ((chunk.len % 2) != 0)
! 120: {
! 121: return FALSE;
! 122: }
! 123:
! 124: len = chunk.len / 2;
! 125:
! 126: if (!BN_bin2bn(chunk.ptr, len, a) ||
! 127: !BN_bin2bn(chunk.ptr + len, len, b))
! 128: {
! 129: return FALSE;
! 130: }
! 131:
! 132: return TRUE;
! 133: }
! 134:
! 135: /**
! 136: * Described in header.
! 137: */
! 138: bool openssl_bn2chunk(const BIGNUM *bn, chunk_t *chunk)
! 139: {
! 140: *chunk = chunk_alloc(BN_num_bytes(bn));
! 141: if (BN_bn2bin(bn, chunk->ptr) == chunk->len)
! 142: {
! 143: if (chunk->len && chunk->ptr[0] & 0x80)
! 144: { /* if MSB is set, prepend a zero to make it non-negative */
! 145: *chunk = chunk_cat("cm", chunk_from_chars(0x00), *chunk);
! 146: }
! 147: return TRUE;
! 148: }
! 149: chunk_free(chunk);
! 150: return FALSE;
! 151: }
! 152:
! 153: /**
! 154: * Described in header.
! 155: */
! 156: chunk_t openssl_asn1_obj2chunk(const ASN1_OBJECT *asn1)
! 157: {
! 158: if (asn1)
! 159: {
! 160: return chunk_create((u_char*)OBJ_get0_data(asn1), OBJ_length(asn1));
! 161: }
! 162: return chunk_empty;
! 163: }
! 164:
! 165: /**
! 166: * Described in header.
! 167: */
! 168: chunk_t openssl_asn1_str2chunk(const ASN1_STRING *asn1)
! 169: {
! 170: if (asn1)
! 171: {
! 172: return chunk_create((u_char*)ASN1_STRING_get0_data(asn1),
! 173: ASN1_STRING_length(asn1));
! 174: }
! 175: return chunk_empty;
! 176: }
! 177:
! 178: /**
! 179: * Convert a X509 name to a ID_DER_ASN1_DN identification_t
! 180: */
! 181: identification_t *openssl_x509_name2id(X509_NAME *name)
! 182: {
! 183: if (name)
! 184: {
! 185: identification_t *id;
! 186: chunk_t chunk;
! 187:
! 188: chunk = openssl_i2chunk(X509_NAME, name);
! 189: if (chunk.len)
! 190: {
! 191: id = identification_create_from_encoding(ID_DER_ASN1_DN, chunk);
! 192: free(chunk.ptr);
! 193: return id;
! 194: }
! 195: }
! 196: return NULL;
! 197: }
! 198:
! 199: /**
! 200: * We can't include <asn1/asn1.h>, as the ASN1_ definitions would clash
! 201: * with OpenSSL. Redeclare what we need.
! 202: */
! 203: int asn1_known_oid(chunk_t);
! 204: time_t asn1_to_time(chunk_t *,int);
! 205:
! 206: /**
! 207: * Described in header.
! 208: */
! 209: int openssl_asn1_known_oid(const ASN1_OBJECT *obj)
! 210: {
! 211: return asn1_known_oid(openssl_asn1_obj2chunk(obj));
! 212: }
! 213:
! 214: /**
! 215: * Described in header.
! 216: */
! 217: time_t openssl_asn1_to_time(const ASN1_TIME *time)
! 218: {
! 219: chunk_t chunk;
! 220:
! 221: if (time)
! 222: {
! 223: chunk = openssl_asn1_str2chunk(time);
! 224: switch (time->type)
! 225: {
! 226: case V_ASN1_UTCTIME:
! 227: case V_ASN1_GENERALIZEDTIME:
! 228: return asn1_to_time(&chunk, time->type);
! 229: default:
! 230: break;
! 231: }
! 232: }
! 233: DBG1(DBG_LIB, "invalid ASN1 time");
! 234: return 0;
! 235: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>