- x509 certificate loading with pluto asn1 code
- x509 needs a lot more attention!
This commit is contained in:
@@ -25,4 +25,3 @@ $(BUILD_DIR)definitions.o : $(LIB_DIR)definitions.c $(LIB_DIR)definitions.h
|
||||
include $(MAIN_DIR)lib/crypto/Makefile.transforms
|
||||
include $(MAIN_DIR)lib/utils/Makefile.utils
|
||||
include $(MAIN_DIR)lib/asn1/Makefile.asn1
|
||||
include $(MAIN_DIR)lib/asn1-pluto/Makefile.asn1
|
||||
|
||||
@@ -12,14 +12,14 @@
|
||||
# for more details.
|
||||
#
|
||||
|
||||
ASN1_DIR= $(LIB_DIR)asn1-pluto/
|
||||
ASN1_DIR= $(LIB_DIR)asn1/
|
||||
|
||||
|
||||
LIB_OBJS+= $(BUILD_DIR)oid.o
|
||||
$(BUILD_DIR)oid.o : $(ASN1_DIR)oid.c $(ASN1_DIR)oid.h
|
||||
$(CC) $(CFLAGS) -c -o $@ $<
|
||||
LIB_OBJS+= $(BUILD_DIR)asn1-pluto.o
|
||||
$(BUILD_DIR)asn1-pluto.o : $(ASN1_DIR)asn1-pluto.c $(ASN1_DIR)asn1-pluto.h
|
||||
LIB_OBJS+= $(BUILD_DIR)asn1.o
|
||||
$(BUILD_DIR)asn1.o : $(ASN1_DIR)asn1.c $(ASN1_DIR)asn1.h
|
||||
$(CC) $(CFLAGS) -c -o $@ $<
|
||||
LIB_OBJS+= $(BUILD_DIR)pem.o
|
||||
$(BUILD_DIR)pem.o : $(ASN1_DIR)pem.c $(ASN1_DIR)pem.h
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "asn1-pluto.h"
|
||||
#include "asn1.h"
|
||||
#include "oid.h"
|
||||
|
||||
#include <utils/logger_manager.h>
|
||||
|
||||
+9
-10
@@ -23,15 +23,14 @@
|
||||
|
||||
|
||||
/* Defines some primitive ASN1 types */
|
||||
|
||||
typedef enum {
|
||||
ASN1_EOC = 0x00,
|
||||
ASN1_BOOLEAN = 0x01,
|
||||
ASN1_INTEGER = 0x02,
|
||||
ASN1_EOC = 0x00,
|
||||
ASN1_BOOLEAN = 0x01,
|
||||
ASN1_INTEGER = 0x02,
|
||||
ASN1_BIT_STRING = 0x03,
|
||||
ASN1_OCTET_STRING = 0x04,
|
||||
ASN1_NULL = 0x05,
|
||||
ASN1_OID = 0x06,
|
||||
ASN1_NULL = 0x05,
|
||||
ASN1_OID = 0x06,
|
||||
ASN1_ENUMERATED = 0x0A,
|
||||
ASN1_UTF8STRING = 0x0C,
|
||||
ASN1_NUMERICSTRING = 0x12,
|
||||
@@ -39,7 +38,7 @@ typedef enum {
|
||||
ASN1_T61STRING = 0x14,
|
||||
ASN1_VIDEOTEXSTRING = 0x15,
|
||||
ASN1_IA5STRING = 0x16,
|
||||
ASN1_UTCTIME = 0x17,
|
||||
ASN1_UTCTIME = 0x17,
|
||||
ASN1_GENERALIZEDTIME = 0x18,
|
||||
ASN1_GRAPHICSTRING = 0x19,
|
||||
ASN1_VISIBLESTRING = 0x1A,
|
||||
@@ -49,9 +48,9 @@ typedef enum {
|
||||
|
||||
ASN1_CONSTRUCTED = 0x20,
|
||||
|
||||
ASN1_SEQUENCE = 0x30,
|
||||
ASN1_SEQUENCE = 0x30,
|
||||
|
||||
ASN1_SET = 0x31,
|
||||
ASN1_SET = 0x31,
|
||||
|
||||
ASN1_CONTEXT_S_0 = 0x80,
|
||||
ASN1_CONTEXT_S_1 = 0x81,
|
||||
@@ -99,7 +98,7 @@ typedef struct {
|
||||
bool implicit;
|
||||
u_int level0;
|
||||
u_int loopAddr[ASN1_MAX_LEVEL+1];
|
||||
chunk_t blobs[ASN1_MAX_LEVEL+2];
|
||||
chunk_t blobs[ASN1_MAX_LEVEL+2];
|
||||
} asn1_ctx_t;
|
||||
|
||||
/* some common prefabricated ASN.1 constants */
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,138 +0,0 @@
|
||||
/* Support of X.509 certificates
|
||||
* Copyright (C) 2000 Andreas Hess, Patric Lichtsteiner, Roger Wegmann
|
||||
* Copyright (C) 2001 Marco Bertossa, Andreas Schleiss
|
||||
* Copyright (C) 2002 Mario Strasser
|
||||
* Copyright (C) 2000-2004 Andreas Steffen, Zuercher Hochschule Winterthur
|
||||
*
|
||||
* 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,v 1.10 2005/12/06 22:52:44 as Exp $
|
||||
*/
|
||||
|
||||
#ifndef _X509_H
|
||||
#define _X509_H
|
||||
|
||||
#include "pkcs1.h"
|
||||
#include "id.h"
|
||||
|
||||
/* Definition of generalNames kinds */
|
||||
|
||||
typedef enum {
|
||||
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
|
||||
} generalNames_t;
|
||||
|
||||
/* access structure for a GeneralName */
|
||||
|
||||
typedef struct generalName generalName_t;
|
||||
|
||||
struct generalName {
|
||||
generalName_t *next;
|
||||
generalNames_t kind;
|
||||
chunk_t name;
|
||||
};
|
||||
|
||||
/* access structure for an X.509v3 certificate */
|
||||
|
||||
typedef struct x509cert x509cert_t;
|
||||
|
||||
struct x509cert {
|
||||
x509cert_t *next;
|
||||
time_t installed;
|
||||
int count;
|
||||
bool smartcard;
|
||||
u_char authority_flags;
|
||||
chunk_t certificate;
|
||||
chunk_t tbsCertificate;
|
||||
u_int version;
|
||||
chunk_t serialNumber;
|
||||
/* signature */
|
||||
int sigAlg;
|
||||
chunk_t issuer;
|
||||
/* validity */
|
||||
time_t notBefore;
|
||||
time_t notAfter;
|
||||
chunk_t subject;
|
||||
/* subjectPublicKeyInfo */
|
||||
enum pubkey_alg subjectPublicKeyAlgorithm;
|
||||
chunk_t subjectPublicKey;
|
||||
chunk_t modulus;
|
||||
chunk_t publicExponent;
|
||||
/* issuerUniqueID */
|
||||
/* subjectUniqueID */
|
||||
/* v3 extensions */
|
||||
/* extension */
|
||||
/* extension */
|
||||
/* extnID */
|
||||
/* critical */
|
||||
/* extnValue */
|
||||
bool isCA;
|
||||
bool isOcspSigner; /* ocsp */
|
||||
chunk_t subjectKeyID;
|
||||
chunk_t authKeyID;
|
||||
chunk_t authKeySerialNumber;
|
||||
chunk_t accessLocation; /* ocsp */
|
||||
generalName_t *subjectAltName;
|
||||
generalName_t *crlDistributionPoints;
|
||||
/* signatureAlgorithm */
|
||||
int algorithm;
|
||||
chunk_t signature;
|
||||
};
|
||||
|
||||
/* used for initialization */
|
||||
extern const x509cert_t empty_x509cert;
|
||||
|
||||
extern bool same_serial(chunk_t a, chunk_t b);
|
||||
extern bool same_keyid(chunk_t a, chunk_t b);
|
||||
extern bool same_dn(chunk_t a, chunk_t b);
|
||||
extern bool match_dn(chunk_t a, chunk_t b, int *wildcards);
|
||||
extern bool same_x509cert(const x509cert_t *a, const x509cert_t *b);
|
||||
extern void hex_str(chunk_t bin, chunk_t *str);
|
||||
extern int dn_count_wildcards(chunk_t dn);
|
||||
extern int dntoa(char *dst, size_t dstlen, chunk_t dn);
|
||||
extern int dntoa_or_null(char *dst, size_t dstlen, chunk_t dn
|
||||
, const char* null_dn);
|
||||
extern err_t atodn(char *src, chunk_t *dn);
|
||||
extern void gntoid(struct id *id, const generalName_t *gn);
|
||||
extern void compute_subjectKeyID(x509cert_t *cert, chunk_t subjectKeyID);
|
||||
extern void select_x509cert_id(x509cert_t *cert, struct id *end_id);
|
||||
extern bool parse_x509cert(chunk_t blob, u_int level0, x509cert_t *cert);
|
||||
extern time_t parse_time(chunk_t blob, int level0);
|
||||
extern void parse_authorityKeyIdentifier(chunk_t blob, int level0
|
||||
, chunk_t *authKeyID, chunk_t *authKeySerialNumber);
|
||||
extern chunk_t get_directoryName(chunk_t blob, int level, bool implicit);
|
||||
extern err_t check_validity(const x509cert_t *cert, time_t *until);
|
||||
extern bool check_signature(chunk_t tbs, chunk_t sig, int digest_alg
|
||||
, int enc_alg, const x509cert_t *issuer_cert);
|
||||
extern bool verify_x509cert(const x509cert_t *cert, bool strict, time_t *until);
|
||||
extern x509cert_t* add_x509cert(x509cert_t *cert);
|
||||
extern x509cert_t* get_x509cert(chunk_t issuer, chunk_t serial, chunk_t keyid
|
||||
, x509cert_t* chain);
|
||||
extern void build_x509cert(x509cert_t *cert, const RSA_public_key_t *cert_key
|
||||
, const RSA_private_key_t *signer_key);
|
||||
extern chunk_t build_subjectAltNames(generalName_t *subjectAltNames);
|
||||
extern void share_x509cert(x509cert_t *cert);
|
||||
extern void release_x509cert(x509cert_t *cert);
|
||||
extern void free_x509cert(x509cert_t *cert);
|
||||
extern void store_x509certs(x509cert_t **firstcert, bool strict);
|
||||
extern void list_x509cert_chain(const char *caption, x509cert_t* cert
|
||||
, u_char auth_flags, bool utc);
|
||||
extern void list_x509_end_certs(bool utc);
|
||||
extern void free_generalNames(generalName_t* gn, bool free_name);
|
||||
|
||||
#endif /* _X509_H */
|
||||
@@ -32,6 +32,6 @@ LIB_OBJS+= $(BUILD_DIR)prf_plus.o
|
||||
$(BUILD_DIR)prf_plus.o : $(CRYPTO_DIR)prf_plus.c $(CRYPTO_DIR)prf_plus.h
|
||||
$(CC) $(CFLAGS) -c -o $@ $<
|
||||
|
||||
LIB_OBJS+= $(BUILD_DIR)certificate.o
|
||||
$(BUILD_DIR)certificate.o : $(CRYPTO_DIR)certificate.c $(CRYPTO_DIR)certificate.h
|
||||
LIB_OBJS+= $(BUILD_DIR)x509.o
|
||||
$(BUILD_DIR)x509.o : $(CRYPTO_DIR)x509.c $(CRYPTO_DIR)x509.h
|
||||
$(CC) $(CFLAGS) -c -o $@ $<
|
||||
|
||||
@@ -1,231 +0,0 @@
|
||||
/**
|
||||
* @file certificate.c
|
||||
*
|
||||
* @brief Implementation of certificate_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 <gmp.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "certificate.h"
|
||||
|
||||
#include <daemon.h>
|
||||
#include <asn1/der_decoder.h>
|
||||
|
||||
|
||||
typedef struct private_certificate_t private_certificate_t;
|
||||
|
||||
/**
|
||||
* Private data of a certificate_t object.
|
||||
*/
|
||||
struct private_certificate_t {
|
||||
/**
|
||||
* Public interface for this signer.
|
||||
*/
|
||||
certificate_t public;
|
||||
|
||||
u_int version;
|
||||
|
||||
u_int serial;
|
||||
|
||||
chunk_t sign_alg;
|
||||
|
||||
time_t not_before;
|
||||
|
||||
time_t not_after;
|
||||
|
||||
chunk_t pubkey;
|
||||
|
||||
chunk_t pubkey_alg;
|
||||
|
||||
bool has_issuer_uid;
|
||||
chunk_t issuer_uid;
|
||||
|
||||
bool has_subject_uid;
|
||||
chunk_t subject_uid;
|
||||
|
||||
chunk_t tbs_cert;
|
||||
chunk_t signature;
|
||||
|
||||
rsa_public_key_t *public_key;
|
||||
};
|
||||
|
||||
#define OSET(x) offsetof(private_certificate_t, x)
|
||||
|
||||
/**
|
||||
* Rules for de-/encoding of a certificate from/in ASN1
|
||||
*/
|
||||
static asn1_rule_t certificate_rules[] = {
|
||||
{ASN1_SEQUENCE, 0, 0, 0 }, /* certificate */
|
||||
{ ASN1_SEQUENCE, ASN1_RAW, OSET(tbs_cert), 0 }, /* tbsCertificate */
|
||||
{ ASN1_TAG_E_0, ASN1_DEFAULT, OSET(version), 0 }, /* EXPLICIT */
|
||||
{ ASN1_INTEGER, ASN1_DEFAULT, OSET(version), 0 }, /* version DEFAULT v1(0) */
|
||||
{ ASN1_INTEGER, 0, OSET(serial), 0 }, /* serialNumber */
|
||||
{ ASN1_SEQUENCE, 0, 0, 0 }, /* signature */
|
||||
{ ASN1_OID, 0, OSET(sign_alg), 0 }, /* algorithm-oid */
|
||||
{ ASN1_NULL, 0, 0, 0 }, /* parameters */
|
||||
{ ASN1_END, 0, 0, 0 }, /* signature */
|
||||
{ ASN1_SEQUENCE, ASN1_OF, 0, 0 }, /* issuer */
|
||||
// { ASN1_SET, ASN1_OF, 0, 0, }, /* RelativeDistinguishedName */
|
||||
// { ASN1_SEQUENCE, 0, 0, 0, }, /* AttributeTypeAndValue */
|
||||
// { ASN1_OID, 0, 0, 0 }, /* AttributeType */
|
||||
// { ASN1_ANY, 0, 0, 0 }, /* AttributeValue */
|
||||
// { ASN1_END, 0, 0, 0 }, /* AttributeTypeAndValue */
|
||||
// { ASN1_END, 0, 0, 0 }, /* RelativeDistinguishedName */
|
||||
{ ASN1_END, 0, 0, 0 }, /* issuer */
|
||||
{ ASN1_SEQUENCE, 0, 0, 0 }, /* validity */
|
||||
{ ASN1_CHOICE, 0, 0, 0 }, /* notBefore */
|
||||
{ ASN1_UTCTIME, 0, OSET(not_before), 0 }, /* utcTime */
|
||||
{ ASN1_GENERALIZEDTIME, 0, OSET(not_before), 0 }, /* generalTime */
|
||||
{ ASN1_END, 0, 0, 0 }, /* notBefore */
|
||||
{ ASN1_CHOICE, 0, 0, 0 }, /* notAfter */
|
||||
{ ASN1_UTCTIME, 0, OSET(not_after), 0 }, /* utcTime */
|
||||
{ ASN1_GENERALIZEDTIME, 0, OSET(not_after), 0 }, /* generalTime */
|
||||
{ ASN1_END, 0, 0, 0 }, /* notAfter */
|
||||
{ ASN1_END, 0, 0, 0 }, /* validity */
|
||||
{ ASN1_SEQUENCE, ASN1_OF, 0, 0 }, /* subject */
|
||||
// { ASN1_SET, ASN1_OF, 0, 0, }, /* RelativeDistinguishedName */
|
||||
// { ASN1_SEQUENCE, 0, 0, 0, }, /* AttributeTypeAndValue */
|
||||
// { ASN1_OID, 0, 0, 0 }, /* AttributeType */
|
||||
// { ASN1_ANY, 0, 0, 0 }, /* AttributeValue */
|
||||
// { ASN1_END, 0, 0, 0 }, /* AttributeTypeAndValue */
|
||||
// { ASN1_END, 0, 0, 0 }, /* RelativeDistinguishedName */
|
||||
{ ASN1_END, 0, 0, 0 }, /* subject */
|
||||
{ ASN1_SEQUENCE, 0, 0, 0 }, /* subjectPublicKeyInfo */
|
||||
{ ASN1_SEQUENCE, 0, 0, 0 }, /* algorithm */
|
||||
{ ASN1_OID, 0, OSET(pubkey_alg), 0 }, /* algorithm-oid */
|
||||
{ ASN1_NULL, 0, 0, 0 }, /* parameters */
|
||||
{ ASN1_END, 0, 0, 0 }, /* algorithm */
|
||||
{ ASN1_BITSTRING, 0, OSET(pubkey), 0 }, /* subjectPublicKey */
|
||||
{ ASN1_END, 0, 0, 0 }, /* subjectPublicKeyInfo */
|
||||
{ ASN1_TAG_I_1, ASN1_OPTIONAL, 0, OSET(has_issuer_uid)}, /* IMPLICIT */
|
||||
{ ASN1_BITSTRING, ASN1_OPTIONAL, OSET(issuer_uid), 0 }, /* issuerUniqueID OPTIONAL */
|
||||
{ ASN1_TAG_I_2, ASN1_OPTIONAL, 0, OSET(has_subject_uid)},/* IMPLICIT */
|
||||
{ ASN1_BITSTRING, ASN1_OPTIONAL, OSET(subject_uid), 0 }, /* subjectUniqueID OPTIONAL */
|
||||
{ ASN1_TAG_E_3, ASN1_OPTIONAL, 0, 0 }, /* EXPLICIT */
|
||||
{ ASN1_SEQUENCE, ASN1_OF|ASN1_OPTIONAL, 0, 0 }, /* extensions OPTIONAL */
|
||||
// { ASN1_SEQUENCE, 0, 0, 0, }, /* extension */
|
||||
// { ASN1_OID, 0, 0, 0 }, /* extnID */
|
||||
// { ASN1_BOOLEAN, ASN1_DEFAULT, 0, FALSE }, /* critical */
|
||||
// { ASN1_OCTETSTRING, 0, 0, 0, }, /* extnValue */
|
||||
// { ASN1_END, 0, 0, 0, }, /* extension */
|
||||
{ ASN1_END, 0, 0, 0, }, /* extensions */
|
||||
{ ASN1_END, 0, 0, 0 }, /* tbsCertificate */
|
||||
{ ASN1_SEQUENCE, 0, 0, 0 }, /* signatureAlgorithm */
|
||||
{ ASN1_OID, 0, OSET(sign_alg), 0 }, /* algorithm-oid */
|
||||
{ ASN1_NULL, 0, 0, 0 }, /* parameters */
|
||||
{ ASN1_END, 0, 0, 0 }, /* signatureAlgorithm */
|
||||
{ ASN1_BITSTRING, 0, OSET(signature), 0 }, /* signatureValue */
|
||||
{ASN1_END, 0, 0, 0 }, /* certificate */
|
||||
};
|
||||
|
||||
/**
|
||||
* Implementation of certificate.get_public_key.
|
||||
*/
|
||||
static rsa_public_key_t *get_public_key(private_certificate_t *this)
|
||||
{
|
||||
return this->public_key->clone(this->public_key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of certificate.destroy.
|
||||
*/
|
||||
static void destroy(private_certificate_t *this)
|
||||
{
|
||||
this->public_key->destroy(this->public_key);
|
||||
free(this->pubkey.ptr);
|
||||
free(this->signature.ptr);
|
||||
free(this->tbs_cert.ptr);
|
||||
free(this);
|
||||
}
|
||||
|
||||
/*
|
||||
* Described in header.
|
||||
*/
|
||||
certificate_t *certificate_create_from_chunk(chunk_t chunk)
|
||||
{
|
||||
private_certificate_t *this = malloc_thing(private_certificate_t);
|
||||
der_decoder_t *dd;
|
||||
|
||||
/* public functions */
|
||||
this->public.get_public_key = (rsa_public_key_t *(*) (certificate_t*))get_public_key;
|
||||
this->public.destroy = (void (*) (certificate_t*))destroy;
|
||||
|
||||
/* initialize */
|
||||
this->pubkey = CHUNK_INITIALIZER;
|
||||
this->signature = CHUNK_INITIALIZER;
|
||||
this->tbs_cert = CHUNK_INITIALIZER;
|
||||
|
||||
dd = der_decoder_create(certificate_rules);
|
||||
|
||||
if (dd->decode(dd, chunk, this) != SUCCESS)
|
||||
{
|
||||
free(this);
|
||||
dd->destroy(dd);
|
||||
return NULL;
|
||||
}
|
||||
dd->destroy(dd);
|
||||
|
||||
this->public_key = rsa_public_key_create_from_chunk(this->pubkey);
|
||||
if (this->public_key == NULL)
|
||||
{
|
||||
free(this->pubkey.ptr);
|
||||
free(this);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return &this->public;
|
||||
}
|
||||
|
||||
/*
|
||||
* Described in header.
|
||||
*/
|
||||
certificate_t *certificate_create_from_file(char *filename)
|
||||
{
|
||||
struct stat stb;
|
||||
FILE *file;
|
||||
char *buffer;
|
||||
chunk_t chunk;
|
||||
|
||||
if (stat(filename, &stb) == -1)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
buffer = alloca(stb.st_size);
|
||||
|
||||
file = fopen(filename, "r");
|
||||
if (file == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (fread(buffer, stb.st_size, 1, file) == -1)
|
||||
{
|
||||
fclose(file);
|
||||
return NULL;
|
||||
}
|
||||
fclose(file);
|
||||
|
||||
chunk.ptr = buffer;
|
||||
chunk.len = stb.st_size;
|
||||
|
||||
return certificate_create_from_chunk(chunk);
|
||||
}
|
||||
@@ -1,80 +0,0 @@
|
||||
/**
|
||||
* @file certificate.h
|
||||
*
|
||||
* @brief Interface of certificate_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 CERTIFICATE_H_
|
||||
#define CERTIFICATE_H_
|
||||
|
||||
#include <types.h>
|
||||
#include <definitions.h>
|
||||
#include <crypto/rsa/rsa_public_key.h>
|
||||
#include <utils/identification.h>
|
||||
#include <utils/iterator.h>
|
||||
|
||||
|
||||
typedef struct certificate_t certificate_t;
|
||||
|
||||
/**
|
||||
* @brief X509 certificate.
|
||||
*
|
||||
* @b Constructors:
|
||||
* - certificate_create_from_chunk()
|
||||
*
|
||||
* @ingroup transforms
|
||||
*/
|
||||
struct certificate_t {
|
||||
|
||||
/**
|
||||
* @brief Get the RSA public key from the certificate.
|
||||
*
|
||||
* @param this calling object
|
||||
* @return public_key
|
||||
*/
|
||||
rsa_public_key_t *(*get_public_key) (certificate_t *this);
|
||||
|
||||
identification_t *(*get_issuer) (certificate_t *this);
|
||||
identification_t *(*get_subject) (certificate_t *this);
|
||||
iterator_t *(*create_subjectaltname_iter) (certificate_t *this);
|
||||
iterator_t *(*create_issueraltname_iter) (certificate_t *this);
|
||||
bool (*belongs_to) (certificate_t *this, identification_t *subject);
|
||||
bool (*issued_by) (certificate_t *this, identification_t *issuer);
|
||||
bool (*validate) (certificate_t *this, rsa_public_key_t *signer);
|
||||
|
||||
/**
|
||||
* @brief Destroys the private key.
|
||||
*
|
||||
* @param this private key to destroy
|
||||
*/
|
||||
void (*destroy) (certificate_t *this);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Read a certificate from a blob.
|
||||
*
|
||||
* @return created certificate_t.
|
||||
*
|
||||
* @ingroup transforms
|
||||
*/
|
||||
certificate_t *certificate_create_from_chunk(chunk_t chunk);
|
||||
|
||||
certificate_t *certificate_create_from_file(char *filename);
|
||||
|
||||
#endif /* CERTIFICATE_H_ */
|
||||
@@ -28,13 +28,7 @@
|
||||
#include "rsa_private_key.h"
|
||||
|
||||
#include <daemon.h>
|
||||
#ifdef NEW_ASN1
|
||||
# include <asn1/asn1.h>
|
||||
# include <asn1/der_decoder.h>
|
||||
#else
|
||||
# include <asn1-pluto/asn1-pluto.h>
|
||||
#endif
|
||||
|
||||
#include <asn1/asn1.h>
|
||||
|
||||
/*
|
||||
* Oids for hash algorithms are defined in
|
||||
@@ -143,41 +137,8 @@ struct private_rsa_private_key_t {
|
||||
|
||||
};
|
||||
|
||||
#ifdef NEW_ASN1
|
||||
/**
|
||||
* Rules for de-/encoding of a private key from/in ASN1
|
||||
*/
|
||||
static asn1_rule_t rsa_private_key_rules[] = {
|
||||
{ASN1_SEQUENCE, 0, 0, 0},
|
||||
{ ASN1_INTEGER, 0, offsetof(private_rsa_private_key_t, version), 0},
|
||||
{ ASN1_INTEGER, ASN1_MPZ, offsetof(private_rsa_private_key_t, n), 0},
|
||||
{ ASN1_INTEGER, ASN1_MPZ, offsetof(private_rsa_private_key_t, e), 0},
|
||||
{ ASN1_INTEGER, ASN1_MPZ, offsetof(private_rsa_private_key_t, d), 0},
|
||||
{ ASN1_INTEGER, ASN1_MPZ, offsetof(private_rsa_private_key_t, p), 0},
|
||||
{ ASN1_INTEGER, ASN1_MPZ, offsetof(private_rsa_private_key_t, q), 0},
|
||||
{ ASN1_INTEGER, ASN1_MPZ, offsetof(private_rsa_private_key_t, exp1), 0},
|
||||
{ ASN1_INTEGER, ASN1_MPZ, offsetof(private_rsa_private_key_t, exp2), 0},
|
||||
{ ASN1_INTEGER, ASN1_MPZ, offsetof(private_rsa_private_key_t, coeff), 0},
|
||||
{ASN1_END, 0, 0, 0},
|
||||
};
|
||||
#else
|
||||
struct {
|
||||
const char *name;
|
||||
size_t offset;
|
||||
} RSA_private_field[] = {
|
||||
{ "Modulus", offsetof(private_rsa_private_key_t, n) },
|
||||
{ "PublicExponent", offsetof(private_rsa_private_key_t, e) },
|
||||
{ "PrivateExponent", offsetof(private_rsa_private_key_t, d) },
|
||||
{ "Prime1", offsetof(private_rsa_private_key_t, p) },
|
||||
{ "Prime2", offsetof(private_rsa_private_key_t, q) },
|
||||
{ "Exponent1", offsetof(private_rsa_private_key_t, exp1) },
|
||||
{ "Exponent2", offsetof(private_rsa_private_key_t, exp2) },
|
||||
{ "Coefficient", offsetof(private_rsa_private_key_t, coeff) },
|
||||
};
|
||||
|
||||
/* ASN.1 definition of a PKCS#1 RSA private key */
|
||||
|
||||
static const asn1Object_t privkeyObjects[] = {
|
||||
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 */
|
||||
@@ -197,13 +158,16 @@ static const asn1Object_t privkeyObjects[] = {
|
||||
{ 1, "end opt or loop", ASN1_EOC, ASN1_END } /* 15 */
|
||||
};
|
||||
|
||||
#define PKCS1_PRIV_KEY_VERSION 1
|
||||
#define PKCS1_PRIV_KEY_MODULUS 2
|
||||
#define PKCS1_PRIV_KEY_PUB_EXP 3
|
||||
#define PKCS1_PRIV_KEY_COEFF 9
|
||||
#define PKCS1_PRIV_KEY_ROOF 16
|
||||
#endif
|
||||
|
||||
#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
|
||||
|
||||
static private_rsa_private_key_t *rsa_private_key_create_empty();
|
||||
|
||||
@@ -628,7 +592,6 @@ rsa_private_key_t *rsa_private_key_create(size_t key_size)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
mpz_init(t);
|
||||
mpz_init(n);
|
||||
mpz_init(d);
|
||||
@@ -636,7 +599,6 @@ rsa_private_key_t *rsa_private_key_create(size_t key_size)
|
||||
mpz_init(exp2);
|
||||
mpz_init(coeff);
|
||||
|
||||
|
||||
/* Swapping Primes so p is larger then q */
|
||||
if (mpz_cmp(p, q) < 0)
|
||||
{
|
||||
@@ -692,48 +654,6 @@ rsa_private_key_t *rsa_private_key_create(size_t key_size)
|
||||
return &this->public;
|
||||
}
|
||||
|
||||
#ifdef NEW_ASN1
|
||||
/*
|
||||
* see header
|
||||
*/
|
||||
rsa_private_key_t *rsa_private_key_create_from_chunk(chunk_t chunk)
|
||||
{
|
||||
private_rsa_private_key_t *this;
|
||||
der_decoder_t *dd;
|
||||
status_t status;
|
||||
|
||||
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);
|
||||
|
||||
dd = der_decoder_create(rsa_private_key_rules);
|
||||
status = dd->decode(dd, chunk, this);
|
||||
dd->destroy(dd);
|
||||
if (status != SUCCESS)
|
||||
{
|
||||
destroy(this);
|
||||
return NULL;
|
||||
}
|
||||
this->k = (mpz_sizeinbase(this->n, 2) + 7) / 8;
|
||||
|
||||
if (check(this) != SUCCESS)
|
||||
{
|
||||
destroy(this);
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
return &this->public;
|
||||
}
|
||||
}
|
||||
#else
|
||||
/*
|
||||
* see header
|
||||
*/
|
||||
@@ -758,28 +678,46 @@ rsa_private_key_t *rsa_private_key_create_from_chunk(chunk_t blob)
|
||||
|
||||
asn1_init(&ctx, blob, 0, FALSE);
|
||||
|
||||
while (objectID < PKCS1_PRIV_KEY_ROOF)
|
||||
while (objectID < PRIV_KEY_ROOF)
|
||||
{
|
||||
if (!extract_object(privkeyObjects, &objectID, &object, &level, &ctx))
|
||||
if (!extract_object(privkey_objects, &objectID, &object, &level, &ctx))
|
||||
{
|
||||
destroy(this);
|
||||
return FALSE;
|
||||
}
|
||||
if (objectID == PKCS1_PRIV_KEY_VERSION)
|
||||
switch (objectID)
|
||||
{
|
||||
if (object.len > 0 && *object.ptr != 0)
|
||||
{
|
||||
destroy(this);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
else if (objectID >= PKCS1_PRIV_KEY_MODULUS &&
|
||||
objectID <= PKCS1_PRIV_KEY_COEFF)
|
||||
{
|
||||
mpz_t *u = (mpz_t *) ((char *)this
|
||||
+ RSA_private_field[objectID - PKCS1_PRIV_KEY_MODULUS].offset);
|
||||
|
||||
mpz_import(*u, object.len, 1, 1, 1, 0, object.ptr);
|
||||
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++;
|
||||
}
|
||||
@@ -796,7 +734,6 @@ rsa_private_key_t *rsa_private_key_create_from_chunk(chunk_t blob)
|
||||
return &this->public;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* see header
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
|
||||
#include <daemon.h>
|
||||
#include <crypto/hashers/hasher.h>
|
||||
#include <asn1/der_decoder.h>
|
||||
#include <asn1/asn1.h>
|
||||
|
||||
/*
|
||||
* For simplicity,
|
||||
@@ -75,6 +75,17 @@ u_int8_t sha512_oid[] = {
|
||||
0x00,0x04,0x40
|
||||
};
|
||||
|
||||
/* ASN.1 definition public key */
|
||||
static const asn1Object_t pubkey_objects[] = {
|
||||
{ 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
|
||||
|
||||
typedef struct private_rsa_public_key_t private_rsa_public_key_t;
|
||||
|
||||
@@ -139,29 +150,6 @@ struct rsa_public_key_info_t {
|
||||
chunk_t public_key;
|
||||
};
|
||||
|
||||
/**
|
||||
* Rules for de-/encoding of a public key from/in ASN1
|
||||
*/
|
||||
static asn1_rule_t rsa_public_key_rules[] = {
|
||||
{ASN1_SEQUENCE, 0, 0, 0},
|
||||
{ ASN1_INTEGER, ASN1_MPZ, offsetof(private_rsa_public_key_t, n), 0},
|
||||
{ ASN1_INTEGER, ASN1_MPZ, offsetof(private_rsa_public_key_t, e), 0},
|
||||
{ASN1_END, 0, 0, 0},
|
||||
};
|
||||
|
||||
/**
|
||||
* Rules for de-/encoding of a PublicKeyInfo from/in ASN1
|
||||
*/
|
||||
static asn1_rule_t rsa_public_key_info_rules[] = {
|
||||
{ASN1_SEQUENCE, 0, 0, 0},
|
||||
{ ASN1_SEQUENCE, 0, 0, 0},
|
||||
{ ASN1_OID, 0, offsetof(rsa_public_key_info_t, algorithm_oid), 0},
|
||||
{ ASN1_NULL, 0, 0, 0},
|
||||
{ ASN1_END, 0, 0, 0},
|
||||
{ ASN1_BITSTRING, 0, offsetof(rsa_public_key_info_t, public_key), 0},
|
||||
{ASN1_END, 0, 0, 0},
|
||||
};
|
||||
|
||||
private_rsa_public_key_t *rsa_public_key_create_empty();
|
||||
|
||||
/**
|
||||
@@ -398,24 +386,39 @@ private_rsa_public_key_t *rsa_public_key_create_empty()
|
||||
/*
|
||||
* See header
|
||||
*/
|
||||
rsa_public_key_t *rsa_public_key_create_from_chunk(chunk_t chunk)
|
||||
rsa_public_key_t *rsa_public_key_create_from_chunk(chunk_t blob)
|
||||
{
|
||||
der_decoder_t *dd;
|
||||
status_t status;
|
||||
asn1_ctx_t ctx;
|
||||
chunk_t object;
|
||||
u_int level;
|
||||
int objectID = 0;
|
||||
private_rsa_public_key_t *this;
|
||||
|
||||
this = rsa_public_key_create_empty();
|
||||
mpz_init(this->n);
|
||||
mpz_init(this->e);
|
||||
|
||||
dd = der_decoder_create(rsa_public_key_rules);
|
||||
status = dd->decode(dd, chunk, this);
|
||||
dd->destroy(dd);
|
||||
if (status != SUCCESS)
|
||||
asn1_init(&ctx, blob, 0, FALSE);
|
||||
|
||||
while (objectID < PUB_KEY_ROOF)
|
||||
{
|
||||
destroy(this);
|
||||
return NULL;
|
||||
if (!extract_object(pubkey_objects, &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) / 8;
|
||||
return &this->public;
|
||||
}
|
||||
@@ -429,10 +432,6 @@ rsa_public_key_t *rsa_public_key_create_from_file(char *filename)
|
||||
FILE *file;
|
||||
char *buffer;
|
||||
chunk_t chunk;
|
||||
rsa_public_key_info_t key_info = {CHUNK_INITIALIZER, CHUNK_INITIALIZER};
|
||||
der_decoder_t *dd;
|
||||
status_t status;
|
||||
rsa_public_key_t *public_key = NULL;
|
||||
|
||||
if (stat(filename, &stb) == -1)
|
||||
{
|
||||
@@ -455,15 +454,5 @@ rsa_public_key_t *rsa_public_key_create_from_file(char *filename)
|
||||
chunk.ptr = buffer;
|
||||
chunk.len = stb.st_size;
|
||||
|
||||
/* parse public key info first */
|
||||
dd = der_decoder_create(rsa_public_key_info_rules);
|
||||
status = dd->decode(dd, chunk, &key_info);
|
||||
dd->destroy(dd);
|
||||
chunk_free(&key_info.algorithm_oid);
|
||||
if (status == SUCCESS)
|
||||
{
|
||||
public_key = rsa_public_key_create_from_chunk(chunk);
|
||||
}
|
||||
chunk_free(&key_info.public_key);
|
||||
return public_key;
|
||||
return rsa_public_key_create_from_chunk(chunk);
|
||||
}
|
||||
|
||||
Executable
+1691
File diff suppressed because it is too large
Load Diff
Executable
+128
@@ -0,0 +1,128 @@
|
||||
/**
|
||||
* @file x509.h
|
||||
*
|
||||
* @brief Interface of x509_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 X509_H_
|
||||
#define X509_H_
|
||||
|
||||
#include <types.h>
|
||||
#include <definitions.h>
|
||||
#include <crypto/rsa/rsa_public_key.h>
|
||||
#include <utils/identification.h>
|
||||
#include <utils/iterator.h>
|
||||
|
||||
|
||||
typedef struct x509_t x509_t;
|
||||
|
||||
/**
|
||||
* @brief X509 certificate.
|
||||
*
|
||||
* @b Constructors:
|
||||
* - x509_create_from_chunk()
|
||||
* - x509_create_from_file()
|
||||
*
|
||||
* @todo more code cleanup needed!
|
||||
* @todo fix unimplemented functions...
|
||||
* @todo handle memory management
|
||||
*
|
||||
* @ingroup transforms
|
||||
*/
|
||||
struct x509_t {
|
||||
|
||||
/**
|
||||
* @brief Get the RSA public key from the certificate.
|
||||
*
|
||||
* @param this calling object
|
||||
* @return public_key
|
||||
*/
|
||||
rsa_public_key_t *(*get_public_key) (x509_t *this);
|
||||
|
||||
/**
|
||||
* @brief Get the certificate issuers ID.
|
||||
*
|
||||
* @todo implement!
|
||||
*/
|
||||
identification_t *(*get_issuer) (x509_t *this);
|
||||
|
||||
/**
|
||||
* @brief Get the subjects ID.
|
||||
*
|
||||
* @todo implement!
|
||||
*/
|
||||
identification_t *(*get_subject) (x509_t *this);
|
||||
|
||||
/**
|
||||
* @brief Check if a certificate is valid.
|
||||
*
|
||||
* This function uses the issuers public key to verify
|
||||
* the validity of a certificate.
|
||||
*
|
||||
* @todo implement!
|
||||
*/
|
||||
bool (*verify) (x509_t *this, rsa_public_key_t *signer);
|
||||
|
||||
/**
|
||||
* @brief Get the key identifier of the public key.
|
||||
*
|
||||
* @todo implement!
|
||||
*/
|
||||
chunk_t (*get_subject_key_identifier) (x509_t *this);
|
||||
|
||||
/**
|
||||
* @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) (x509_t *this, x509_t *other);
|
||||
|
||||
/**
|
||||
* @brief Destroys the certificate.
|
||||
*
|
||||
* @param this certificate to destroy
|
||||
*/
|
||||
void (*destroy) (x509_t *this);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Read a x509 certificate from a DER encoded blob.
|
||||
*
|
||||
* @param chunk chunk containing DER encoded data
|
||||
* @return created x509_t certificate, or NULL if invalid.
|
||||
*
|
||||
* @ingroup transforms
|
||||
*/
|
||||
x509_t *x509_create_from_chunk(chunk_t chunk);
|
||||
|
||||
/**
|
||||
* @brief Read a x509 certificate from a DER encoded file.
|
||||
*
|
||||
* @param filename file containing DER encoded data
|
||||
* @return created x509_t certificate, or NULL if invalid.
|
||||
*
|
||||
* @ingroup transforms
|
||||
*/
|
||||
x509_t *x509_create_from_file(char *filename);
|
||||
|
||||
#endif /* X509_H_ */
|
||||
+13
-1
@@ -87,13 +87,25 @@ chunk_t chunk_alloc(size_t bytes)
|
||||
return new_chunk;
|
||||
}
|
||||
|
||||
/**
|
||||
* Described in header.
|
||||
*/
|
||||
bool chunk_equals(chunk_t a, chunk_t b)
|
||||
{
|
||||
if (a.ptr == NULL || b.ptr == NULL ||
|
||||
a.len != b.len ||
|
||||
memcmp(a.ptr, b.ptr, a.len) != 0)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Described in header.
|
||||
*/
|
||||
void *clalloc(void * pointer, size_t size)
|
||||
{
|
||||
|
||||
void *data;
|
||||
data = malloc(size);
|
||||
|
||||
|
||||
+13
-7
@@ -31,6 +31,13 @@
|
||||
#include <definitions.h>
|
||||
|
||||
|
||||
/**
|
||||
* General purpose boolean type.
|
||||
*/
|
||||
typedef int bool;
|
||||
#define FALSE 0
|
||||
#define TRUE 1
|
||||
|
||||
typedef enum status_t status_t;
|
||||
|
||||
/**
|
||||
@@ -165,17 +172,16 @@ void chunk_free(chunk_t *chunk);
|
||||
*/
|
||||
chunk_t chunk_alloc(size_t bytes);
|
||||
|
||||
/**
|
||||
* Compare two chunks for equality,
|
||||
* NULL chunks are never equal.
|
||||
*/
|
||||
bool chunk_equals(chunk_t a, chunk_t b);
|
||||
|
||||
/**
|
||||
* Clone a data to a newly allocated buffer
|
||||
*/
|
||||
void *clalloc(void *pointer, size_t size);
|
||||
|
||||
|
||||
/**
|
||||
* General purpose boolean type.
|
||||
*/
|
||||
typedef int bool;
|
||||
#define FALSE 0
|
||||
#define TRUE 1
|
||||
|
||||
#endif /*TYPES_H_*/
|
||||
|
||||
Reference in New Issue
Block a user