Imported OpenSSL 1.1.1a
This commit is contained in:
216
crypto/asn1/a_bitstr.c
Normal file
216
crypto/asn1/a_bitstr.c
Normal file
@@ -0,0 +1,216 @@
|
||||
/*
|
||||
* Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
#include "internal/cryptlib.h"
|
||||
#include <openssl/asn1.h>
|
||||
#include "asn1_locl.h"
|
||||
|
||||
int ASN1_BIT_STRING_set(ASN1_BIT_STRING *x, unsigned char *d, int len)
|
||||
{
|
||||
return ASN1_STRING_set(x, d, len);
|
||||
}
|
||||
|
||||
int i2c_ASN1_BIT_STRING(ASN1_BIT_STRING *a, unsigned char **pp)
|
||||
{
|
||||
int ret, j, bits, len;
|
||||
unsigned char *p, *d;
|
||||
|
||||
if (a == NULL)
|
||||
return 0;
|
||||
|
||||
len = a->length;
|
||||
|
||||
if (len > 0) {
|
||||
if (a->flags & ASN1_STRING_FLAG_BITS_LEFT) {
|
||||
bits = (int)a->flags & 0x07;
|
||||
} else {
|
||||
for (; len > 0; len--) {
|
||||
if (a->data[len - 1])
|
||||
break;
|
||||
}
|
||||
j = a->data[len - 1];
|
||||
if (j & 0x01)
|
||||
bits = 0;
|
||||
else if (j & 0x02)
|
||||
bits = 1;
|
||||
else if (j & 0x04)
|
||||
bits = 2;
|
||||
else if (j & 0x08)
|
||||
bits = 3;
|
||||
else if (j & 0x10)
|
||||
bits = 4;
|
||||
else if (j & 0x20)
|
||||
bits = 5;
|
||||
else if (j & 0x40)
|
||||
bits = 6;
|
||||
else if (j & 0x80)
|
||||
bits = 7;
|
||||
else
|
||||
bits = 0; /* should not happen */
|
||||
}
|
||||
} else
|
||||
bits = 0;
|
||||
|
||||
ret = 1 + len;
|
||||
if (pp == NULL)
|
||||
return ret;
|
||||
|
||||
p = *pp;
|
||||
|
||||
*(p++) = (unsigned char)bits;
|
||||
d = a->data;
|
||||
if (len > 0) {
|
||||
memcpy(p, d, len);
|
||||
p += len;
|
||||
p[-1] &= (0xff << bits);
|
||||
}
|
||||
*pp = p;
|
||||
return ret;
|
||||
}
|
||||
|
||||
ASN1_BIT_STRING *c2i_ASN1_BIT_STRING(ASN1_BIT_STRING **a,
|
||||
const unsigned char **pp, long len)
|
||||
{
|
||||
ASN1_BIT_STRING *ret = NULL;
|
||||
const unsigned char *p;
|
||||
unsigned char *s;
|
||||
int i;
|
||||
|
||||
if (len < 1) {
|
||||
i = ASN1_R_STRING_TOO_SHORT;
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (len > INT_MAX) {
|
||||
i = ASN1_R_STRING_TOO_LONG;
|
||||
goto err;
|
||||
}
|
||||
|
||||
if ((a == NULL) || ((*a) == NULL)) {
|
||||
if ((ret = ASN1_BIT_STRING_new()) == NULL)
|
||||
return NULL;
|
||||
} else
|
||||
ret = (*a);
|
||||
|
||||
p = *pp;
|
||||
i = *(p++);
|
||||
if (i > 7) {
|
||||
i = ASN1_R_INVALID_BIT_STRING_BITS_LEFT;
|
||||
goto err;
|
||||
}
|
||||
/*
|
||||
* We do this to preserve the settings. If we modify the settings, via
|
||||
* the _set_bit function, we will recalculate on output
|
||||
*/
|
||||
ret->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07); /* clear */
|
||||
ret->flags |= (ASN1_STRING_FLAG_BITS_LEFT | i); /* set */
|
||||
|
||||
if (len-- > 1) { /* using one because of the bits left byte */
|
||||
s = OPENSSL_malloc((int)len);
|
||||
if (s == NULL) {
|
||||
i = ERR_R_MALLOC_FAILURE;
|
||||
goto err;
|
||||
}
|
||||
memcpy(s, p, (int)len);
|
||||
s[len - 1] &= (0xff << i);
|
||||
p += len;
|
||||
} else
|
||||
s = NULL;
|
||||
|
||||
ret->length = (int)len;
|
||||
OPENSSL_free(ret->data);
|
||||
ret->data = s;
|
||||
ret->type = V_ASN1_BIT_STRING;
|
||||
if (a != NULL)
|
||||
(*a) = ret;
|
||||
*pp = p;
|
||||
return ret;
|
||||
err:
|
||||
ASN1err(ASN1_F_C2I_ASN1_BIT_STRING, i);
|
||||
if ((a == NULL) || (*a != ret))
|
||||
ASN1_BIT_STRING_free(ret);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* These next 2 functions from Goetz Babin-Ebell.
|
||||
*/
|
||||
int ASN1_BIT_STRING_set_bit(ASN1_BIT_STRING *a, int n, int value)
|
||||
{
|
||||
int w, v, iv;
|
||||
unsigned char *c;
|
||||
|
||||
w = n / 8;
|
||||
v = 1 << (7 - (n & 0x07));
|
||||
iv = ~v;
|
||||
if (!value)
|
||||
v = 0;
|
||||
|
||||
if (a == NULL)
|
||||
return 0;
|
||||
|
||||
a->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07); /* clear, set on write */
|
||||
|
||||
if ((a->length < (w + 1)) || (a->data == NULL)) {
|
||||
if (!value)
|
||||
return 1; /* Don't need to set */
|
||||
c = OPENSSL_clear_realloc(a->data, a->length, w + 1);
|
||||
if (c == NULL) {
|
||||
ASN1err(ASN1_F_ASN1_BIT_STRING_SET_BIT, ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
if (w + 1 - a->length > 0)
|
||||
memset(c + a->length, 0, w + 1 - a->length);
|
||||
a->data = c;
|
||||
a->length = w + 1;
|
||||
}
|
||||
a->data[w] = ((a->data[w]) & iv) | v;
|
||||
while ((a->length > 0) && (a->data[a->length - 1] == 0))
|
||||
a->length--;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ASN1_BIT_STRING_get_bit(const ASN1_BIT_STRING *a, int n)
|
||||
{
|
||||
int w, v;
|
||||
|
||||
w = n / 8;
|
||||
v = 1 << (7 - (n & 0x07));
|
||||
if ((a == NULL) || (a->length < (w + 1)) || (a->data == NULL))
|
||||
return 0;
|
||||
return ((a->data[w] & v) != 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Checks if the given bit string contains only bits specified by
|
||||
* the flags vector. Returns 0 if there is at least one bit set in 'a'
|
||||
* which is not specified in 'flags', 1 otherwise.
|
||||
* 'len' is the length of 'flags'.
|
||||
*/
|
||||
int ASN1_BIT_STRING_check(const ASN1_BIT_STRING *a,
|
||||
const unsigned char *flags, int flags_len)
|
||||
{
|
||||
int i, ok;
|
||||
/* Check if there is one bit set at all. */
|
||||
if (!a || !a->data)
|
||||
return 1;
|
||||
|
||||
/*
|
||||
* Check each byte of the internal representation of the bit string.
|
||||
*/
|
||||
ok = 1;
|
||||
for (i = 0; i < a->length && ok; ++i) {
|
||||
unsigned char mask = i < flags_len ? ~flags[i] : 0xff;
|
||||
/* We are done if there is an unneeded bit set. */
|
||||
ok = (a->data[i] & mask) == 0;
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
234
crypto/asn1/a_d2i_fp.c
Normal file
234
crypto/asn1/a_d2i_fp.c
Normal file
@@ -0,0 +1,234 @@
|
||||
/*
|
||||
* Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <limits.h>
|
||||
#include "internal/cryptlib.h"
|
||||
#include "internal/numbers.h"
|
||||
#include <openssl/buffer.h>
|
||||
#include <openssl/asn1.h>
|
||||
#include "internal/asn1_int.h"
|
||||
|
||||
#ifndef NO_OLD_ASN1
|
||||
# ifndef OPENSSL_NO_STDIO
|
||||
|
||||
void *ASN1_d2i_fp(void *(*xnew) (void), d2i_of_void *d2i, FILE *in, void **x)
|
||||
{
|
||||
BIO *b;
|
||||
void *ret;
|
||||
|
||||
if ((b = BIO_new(BIO_s_file())) == NULL) {
|
||||
ASN1err(ASN1_F_ASN1_D2I_FP, ERR_R_BUF_LIB);
|
||||
return NULL;
|
||||
}
|
||||
BIO_set_fp(b, in, BIO_NOCLOSE);
|
||||
ret = ASN1_d2i_bio(xnew, d2i, b, x);
|
||||
BIO_free(b);
|
||||
return ret;
|
||||
}
|
||||
# endif
|
||||
|
||||
void *ASN1_d2i_bio(void *(*xnew) (void), d2i_of_void *d2i, BIO *in, void **x)
|
||||
{
|
||||
BUF_MEM *b = NULL;
|
||||
const unsigned char *p;
|
||||
void *ret = NULL;
|
||||
int len;
|
||||
|
||||
len = asn1_d2i_read_bio(in, &b);
|
||||
if (len < 0)
|
||||
goto err;
|
||||
|
||||
p = (unsigned char *)b->data;
|
||||
ret = d2i(x, &p, len);
|
||||
err:
|
||||
BUF_MEM_free(b);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void *ASN1_item_d2i_bio(const ASN1_ITEM *it, BIO *in, void *x)
|
||||
{
|
||||
BUF_MEM *b = NULL;
|
||||
const unsigned char *p;
|
||||
void *ret = NULL;
|
||||
int len;
|
||||
|
||||
len = asn1_d2i_read_bio(in, &b);
|
||||
if (len < 0)
|
||||
goto err;
|
||||
|
||||
p = (const unsigned char *)b->data;
|
||||
ret = ASN1_item_d2i(x, &p, len, it);
|
||||
err:
|
||||
BUF_MEM_free(b);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifndef OPENSSL_NO_STDIO
|
||||
void *ASN1_item_d2i_fp(const ASN1_ITEM *it, FILE *in, void *x)
|
||||
{
|
||||
BIO *b;
|
||||
char *ret;
|
||||
|
||||
if ((b = BIO_new(BIO_s_file())) == NULL) {
|
||||
ASN1err(ASN1_F_ASN1_ITEM_D2I_FP, ERR_R_BUF_LIB);
|
||||
return NULL;
|
||||
}
|
||||
BIO_set_fp(b, in, BIO_NOCLOSE);
|
||||
ret = ASN1_item_d2i_bio(it, b, x);
|
||||
BIO_free(b);
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
#define HEADER_SIZE 8
|
||||
#define ASN1_CHUNK_INITIAL_SIZE (16 * 1024)
|
||||
int asn1_d2i_read_bio(BIO *in, BUF_MEM **pb)
|
||||
{
|
||||
BUF_MEM *b;
|
||||
unsigned char *p;
|
||||
int i;
|
||||
size_t want = HEADER_SIZE;
|
||||
uint32_t eos = 0;
|
||||
size_t off = 0;
|
||||
size_t len = 0;
|
||||
|
||||
const unsigned char *q;
|
||||
long slen;
|
||||
int inf, tag, xclass;
|
||||
|
||||
b = BUF_MEM_new();
|
||||
if (b == NULL) {
|
||||
ASN1err(ASN1_F_ASN1_D2I_READ_BIO, ERR_R_MALLOC_FAILURE);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ERR_clear_error();
|
||||
for (;;) {
|
||||
if (want >= (len - off)) {
|
||||
want -= (len - off);
|
||||
|
||||
if (len + want < len || !BUF_MEM_grow_clean(b, len + want)) {
|
||||
ASN1err(ASN1_F_ASN1_D2I_READ_BIO, ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
i = BIO_read(in, &(b->data[len]), want);
|
||||
if ((i < 0) && ((len - off) == 0)) {
|
||||
ASN1err(ASN1_F_ASN1_D2I_READ_BIO, ASN1_R_NOT_ENOUGH_DATA);
|
||||
goto err;
|
||||
}
|
||||
if (i > 0) {
|
||||
if (len + i < len) {
|
||||
ASN1err(ASN1_F_ASN1_D2I_READ_BIO, ASN1_R_TOO_LONG);
|
||||
goto err;
|
||||
}
|
||||
len += i;
|
||||
}
|
||||
}
|
||||
/* else data already loaded */
|
||||
|
||||
p = (unsigned char *)&(b->data[off]);
|
||||
q = p;
|
||||
inf = ASN1_get_object(&q, &slen, &tag, &xclass, len - off);
|
||||
if (inf & 0x80) {
|
||||
unsigned long e;
|
||||
|
||||
e = ERR_GET_REASON(ERR_peek_error());
|
||||
if (e != ASN1_R_TOO_LONG)
|
||||
goto err;
|
||||
else
|
||||
ERR_clear_error(); /* clear error */
|
||||
}
|
||||
i = q - p; /* header length */
|
||||
off += i; /* end of data */
|
||||
|
||||
if (inf & 1) {
|
||||
/* no data body so go round again */
|
||||
if (eos == UINT32_MAX) {
|
||||
ASN1err(ASN1_F_ASN1_D2I_READ_BIO, ASN1_R_HEADER_TOO_LONG);
|
||||
goto err;
|
||||
}
|
||||
eos++;
|
||||
want = HEADER_SIZE;
|
||||
} else if (eos && (slen == 0) && (tag == V_ASN1_EOC)) {
|
||||
/* eos value, so go back and read another header */
|
||||
eos--;
|
||||
if (eos == 0)
|
||||
break;
|
||||
else
|
||||
want = HEADER_SIZE;
|
||||
} else {
|
||||
/* suck in slen bytes of data */
|
||||
want = slen;
|
||||
if (want > (len - off)) {
|
||||
size_t chunk_max = ASN1_CHUNK_INITIAL_SIZE;
|
||||
|
||||
want -= (len - off);
|
||||
if (want > INT_MAX /* BIO_read takes an int length */ ||
|
||||
len + want < len) {
|
||||
ASN1err(ASN1_F_ASN1_D2I_READ_BIO, ASN1_R_TOO_LONG);
|
||||
goto err;
|
||||
}
|
||||
while (want > 0) {
|
||||
/*
|
||||
* Read content in chunks of increasing size
|
||||
* so we can return an error for EOF without
|
||||
* having to allocate the entire content length
|
||||
* in one go.
|
||||
*/
|
||||
size_t chunk = want > chunk_max ? chunk_max : want;
|
||||
|
||||
if (!BUF_MEM_grow_clean(b, len + chunk)) {
|
||||
ASN1err(ASN1_F_ASN1_D2I_READ_BIO, ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
want -= chunk;
|
||||
while (chunk > 0) {
|
||||
i = BIO_read(in, &(b->data[len]), chunk);
|
||||
if (i <= 0) {
|
||||
ASN1err(ASN1_F_ASN1_D2I_READ_BIO,
|
||||
ASN1_R_NOT_ENOUGH_DATA);
|
||||
goto err;
|
||||
}
|
||||
/*
|
||||
* This can't overflow because |len+want| didn't
|
||||
* overflow.
|
||||
*/
|
||||
len += i;
|
||||
chunk -= i;
|
||||
}
|
||||
if (chunk_max < INT_MAX/2)
|
||||
chunk_max *= 2;
|
||||
}
|
||||
}
|
||||
if (off + slen < off) {
|
||||
ASN1err(ASN1_F_ASN1_D2I_READ_BIO, ASN1_R_TOO_LONG);
|
||||
goto err;
|
||||
}
|
||||
off += slen;
|
||||
if (eos == 0) {
|
||||
break;
|
||||
} else
|
||||
want = HEADER_SIZE;
|
||||
}
|
||||
}
|
||||
|
||||
if (off > INT_MAX) {
|
||||
ASN1err(ASN1_F_ASN1_D2I_READ_BIO, ASN1_R_TOO_LONG);
|
||||
goto err;
|
||||
}
|
||||
|
||||
*pb = b;
|
||||
return off;
|
||||
err:
|
||||
BUF_MEM_free(b);
|
||||
return -1;
|
||||
}
|
||||
63
crypto/asn1/a_digest.c
Normal file
63
crypto/asn1/a_digest.c
Normal file
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "internal/cryptlib.h"
|
||||
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/buffer.h>
|
||||
#include <openssl/x509.h>
|
||||
|
||||
#ifndef NO_ASN1_OLD
|
||||
|
||||
int ASN1_digest(i2d_of_void *i2d, const EVP_MD *type, char *data,
|
||||
unsigned char *md, unsigned int *len)
|
||||
{
|
||||
int i;
|
||||
unsigned char *str, *p;
|
||||
|
||||
i = i2d(data, NULL);
|
||||
if ((str = OPENSSL_malloc(i)) == NULL) {
|
||||
ASN1err(ASN1_F_ASN1_DIGEST, ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
p = str;
|
||||
i2d(data, &p);
|
||||
|
||||
if (!EVP_Digest(str, i, md, len, type, NULL)) {
|
||||
OPENSSL_free(str);
|
||||
return 0;
|
||||
}
|
||||
OPENSSL_free(str);
|
||||
return 1;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
int ASN1_item_digest(const ASN1_ITEM *it, const EVP_MD *type, void *asn,
|
||||
unsigned char *md, unsigned int *len)
|
||||
{
|
||||
int i;
|
||||
unsigned char *str = NULL;
|
||||
|
||||
i = ASN1_item_i2d(asn, &str, it);
|
||||
if (!str)
|
||||
return 0;
|
||||
|
||||
if (!EVP_Digest(str, i, md, len, type, NULL)) {
|
||||
OPENSSL_free(str);
|
||||
return 0;
|
||||
}
|
||||
OPENSSL_free(str);
|
||||
return 1;
|
||||
}
|
||||
68
crypto/asn1/a_dup.c
Normal file
68
crypto/asn1/a_dup.c
Normal file
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "internal/cryptlib.h"
|
||||
#include <openssl/asn1.h>
|
||||
|
||||
#ifndef NO_OLD_ASN1
|
||||
|
||||
void *ASN1_dup(i2d_of_void *i2d, d2i_of_void *d2i, void *x)
|
||||
{
|
||||
unsigned char *b, *p;
|
||||
const unsigned char *p2;
|
||||
int i;
|
||||
char *ret;
|
||||
|
||||
if (x == NULL)
|
||||
return NULL;
|
||||
|
||||
i = i2d(x, NULL);
|
||||
b = OPENSSL_malloc(i + 10);
|
||||
if (b == NULL) {
|
||||
ASN1err(ASN1_F_ASN1_DUP, ERR_R_MALLOC_FAILURE);
|
||||
return NULL;
|
||||
}
|
||||
p = b;
|
||||
i = i2d(x, &p);
|
||||
p2 = b;
|
||||
ret = d2i(NULL, &p2, i);
|
||||
OPENSSL_free(b);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* ASN1_ITEM version of dup: this follows the model above except we don't
|
||||
* need to allocate the buffer. At some point this could be rewritten to
|
||||
* directly dup the underlying structure instead of doing and encode and
|
||||
* decode.
|
||||
*/
|
||||
|
||||
void *ASN1_item_dup(const ASN1_ITEM *it, void *x)
|
||||
{
|
||||
unsigned char *b = NULL;
|
||||
const unsigned char *p;
|
||||
long i;
|
||||
void *ret;
|
||||
|
||||
if (x == NULL)
|
||||
return NULL;
|
||||
|
||||
i = ASN1_item_i2d(x, &b, it);
|
||||
if (b == NULL) {
|
||||
ASN1err(ASN1_F_ASN1_ITEM_DUP, ERR_R_MALLOC_FAILURE);
|
||||
return NULL;
|
||||
}
|
||||
p = b;
|
||||
ret = ASN1_item_d2i(NULL, &p, i, it);
|
||||
OPENSSL_free(b);
|
||||
return ret;
|
||||
}
|
||||
82
crypto/asn1/a_gentm.c
Normal file
82
crypto/asn1/a_gentm.c
Normal file
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
/*
|
||||
* GENERALIZEDTIME implementation. Based on UTCTIME
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
#include "internal/cryptlib.h"
|
||||
#include <openssl/asn1.h>
|
||||
#include "asn1_locl.h"
|
||||
|
||||
/* This is the primary function used to parse ASN1_GENERALIZEDTIME */
|
||||
int asn1_generalizedtime_to_tm(struct tm *tm, const ASN1_GENERALIZEDTIME *d)
|
||||
{
|
||||
/* wrapper around asn1_time_to_tm */
|
||||
if (d->type != V_ASN1_GENERALIZEDTIME)
|
||||
return 0;
|
||||
return asn1_time_to_tm(tm, d);
|
||||
}
|
||||
|
||||
int ASN1_GENERALIZEDTIME_check(const ASN1_GENERALIZEDTIME *d)
|
||||
{
|
||||
return asn1_generalizedtime_to_tm(NULL, d);
|
||||
}
|
||||
|
||||
int ASN1_GENERALIZEDTIME_set_string(ASN1_GENERALIZEDTIME *s, const char *str)
|
||||
{
|
||||
ASN1_GENERALIZEDTIME t;
|
||||
|
||||
t.type = V_ASN1_GENERALIZEDTIME;
|
||||
t.length = strlen(str);
|
||||
t.data = (unsigned char *)str;
|
||||
t.flags = 0;
|
||||
|
||||
if (!ASN1_GENERALIZEDTIME_check(&t))
|
||||
return 0;
|
||||
|
||||
if (s != NULL && !ASN1_STRING_copy(s, &t))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
ASN1_GENERALIZEDTIME *ASN1_GENERALIZEDTIME_set(ASN1_GENERALIZEDTIME *s,
|
||||
time_t t)
|
||||
{
|
||||
return ASN1_GENERALIZEDTIME_adj(s, t, 0, 0);
|
||||
}
|
||||
|
||||
ASN1_GENERALIZEDTIME *ASN1_GENERALIZEDTIME_adj(ASN1_GENERALIZEDTIME *s,
|
||||
time_t t, int offset_day,
|
||||
long offset_sec)
|
||||
{
|
||||
struct tm *ts;
|
||||
struct tm data;
|
||||
|
||||
ts = OPENSSL_gmtime(&t, &data);
|
||||
if (ts == NULL)
|
||||
return NULL;
|
||||
|
||||
if (offset_day || offset_sec) {
|
||||
if (!OPENSSL_gmtime_adj(ts, offset_day, offset_sec))
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return asn1_time_from_tm(s, ts, V_ASN1_GENERALIZEDTIME);
|
||||
}
|
||||
|
||||
int ASN1_GENERALIZEDTIME_print(BIO *bp, const ASN1_GENERALIZEDTIME *tm)
|
||||
{
|
||||
if (tm->type != V_ASN1_GENERALIZEDTIME)
|
||||
return 0;
|
||||
return ASN1_TIME_print(bp, tm);
|
||||
}
|
||||
111
crypto/asn1/a_i2d_fp.c
Normal file
111
crypto/asn1/a_i2d_fp.c
Normal file
@@ -0,0 +1,111 @@
|
||||
/*
|
||||
* Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "internal/cryptlib.h"
|
||||
#include <openssl/buffer.h>
|
||||
#include <openssl/asn1.h>
|
||||
|
||||
#ifndef NO_OLD_ASN1
|
||||
|
||||
# ifndef OPENSSL_NO_STDIO
|
||||
int ASN1_i2d_fp(i2d_of_void *i2d, FILE *out, void *x)
|
||||
{
|
||||
BIO *b;
|
||||
int ret;
|
||||
|
||||
if ((b = BIO_new(BIO_s_file())) == NULL) {
|
||||
ASN1err(ASN1_F_ASN1_I2D_FP, ERR_R_BUF_LIB);
|
||||
return 0;
|
||||
}
|
||||
BIO_set_fp(b, out, BIO_NOCLOSE);
|
||||
ret = ASN1_i2d_bio(i2d, b, x);
|
||||
BIO_free(b);
|
||||
return ret;
|
||||
}
|
||||
# endif
|
||||
|
||||
int ASN1_i2d_bio(i2d_of_void *i2d, BIO *out, unsigned char *x)
|
||||
{
|
||||
char *b;
|
||||
unsigned char *p;
|
||||
int i, j = 0, n, ret = 1;
|
||||
|
||||
n = i2d(x, NULL);
|
||||
if (n <= 0)
|
||||
return 0;
|
||||
|
||||
b = OPENSSL_malloc(n);
|
||||
if (b == NULL) {
|
||||
ASN1err(ASN1_F_ASN1_I2D_BIO, ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
p = (unsigned char *)b;
|
||||
i2d(x, &p);
|
||||
|
||||
for (;;) {
|
||||
i = BIO_write(out, &(b[j]), n);
|
||||
if (i == n)
|
||||
break;
|
||||
if (i <= 0) {
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
j += i;
|
||||
n -= i;
|
||||
}
|
||||
OPENSSL_free(b);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef OPENSSL_NO_STDIO
|
||||
int ASN1_item_i2d_fp(const ASN1_ITEM *it, FILE *out, void *x)
|
||||
{
|
||||
BIO *b;
|
||||
int ret;
|
||||
|
||||
if ((b = BIO_new(BIO_s_file())) == NULL) {
|
||||
ASN1err(ASN1_F_ASN1_ITEM_I2D_FP, ERR_R_BUF_LIB);
|
||||
return 0;
|
||||
}
|
||||
BIO_set_fp(b, out, BIO_NOCLOSE);
|
||||
ret = ASN1_item_i2d_bio(it, b, x);
|
||||
BIO_free(b);
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
int ASN1_item_i2d_bio(const ASN1_ITEM *it, BIO *out, void *x)
|
||||
{
|
||||
unsigned char *b = NULL;
|
||||
int i, j = 0, n, ret = 1;
|
||||
|
||||
n = ASN1_item_i2d(x, &b, it);
|
||||
if (b == NULL) {
|
||||
ASN1err(ASN1_F_ASN1_ITEM_I2D_BIO, ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
i = BIO_write(out, &(b[j]), n);
|
||||
if (i == n)
|
||||
break;
|
||||
if (i <= 0) {
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
j += i;
|
||||
n -= i;
|
||||
}
|
||||
OPENSSL_free(b);
|
||||
return ret;
|
||||
}
|
||||
630
crypto/asn1/a_int.c
Normal file
630
crypto/asn1/a_int.c
Normal file
@@ -0,0 +1,630 @@
|
||||
/*
|
||||
* Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "internal/cryptlib.h"
|
||||
#include "internal/numbers.h"
|
||||
#include <limits.h>
|
||||
#include <openssl/asn1.h>
|
||||
#include <openssl/bn.h>
|
||||
#include "asn1_locl.h"
|
||||
|
||||
ASN1_INTEGER *ASN1_INTEGER_dup(const ASN1_INTEGER *x)
|
||||
{
|
||||
return ASN1_STRING_dup(x);
|
||||
}
|
||||
|
||||
int ASN1_INTEGER_cmp(const ASN1_INTEGER *x, const ASN1_INTEGER *y)
|
||||
{
|
||||
int neg, ret;
|
||||
/* Compare signs */
|
||||
neg = x->type & V_ASN1_NEG;
|
||||
if (neg != (y->type & V_ASN1_NEG)) {
|
||||
if (neg)
|
||||
return -1;
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
|
||||
ret = ASN1_STRING_cmp(x, y);
|
||||
|
||||
if (neg)
|
||||
return -ret;
|
||||
else
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*-
|
||||
* This converts a big endian buffer and sign into its content encoding.
|
||||
* This is used for INTEGER and ENUMERATED types.
|
||||
* The internal representation is an ASN1_STRING whose data is a big endian
|
||||
* representation of the value, ignoring the sign. The sign is determined by
|
||||
* the type: if type & V_ASN1_NEG is true it is negative, otherwise positive.
|
||||
*
|
||||
* Positive integers are no problem: they are almost the same as the DER
|
||||
* encoding, except if the first byte is >= 0x80 we need to add a zero pad.
|
||||
*
|
||||
* Negative integers are a bit trickier...
|
||||
* The DER representation of negative integers is in 2s complement form.
|
||||
* The internal form is converted by complementing each octet and finally
|
||||
* adding one to the result. This can be done less messily with a little trick.
|
||||
* If the internal form has trailing zeroes then they will become FF by the
|
||||
* complement and 0 by the add one (due to carry) so just copy as many trailing
|
||||
* zeros to the destination as there are in the source. The carry will add one
|
||||
* to the last none zero octet: so complement this octet and add one and finally
|
||||
* complement any left over until you get to the start of the string.
|
||||
*
|
||||
* Padding is a little trickier too. If the first bytes is > 0x80 then we pad
|
||||
* with 0xff. However if the first byte is 0x80 and one of the following bytes
|
||||
* is non-zero we pad with 0xff. The reason for this distinction is that 0x80
|
||||
* followed by optional zeros isn't padded.
|
||||
*/
|
||||
|
||||
/*
|
||||
* If |pad| is zero, the operation is effectively reduced to memcpy,
|
||||
* and if |pad| is 0xff, then it performs two's complement, ~dst + 1.
|
||||
* Note that in latter case sequence of zeros yields itself, and so
|
||||
* does 0x80 followed by any number of zeros. These properties are
|
||||
* used elsewhere below...
|
||||
*/
|
||||
static void twos_complement(unsigned char *dst, const unsigned char *src,
|
||||
size_t len, unsigned char pad)
|
||||
{
|
||||
unsigned int carry = pad & 1;
|
||||
|
||||
/* Begin at the end of the encoding */
|
||||
dst += len;
|
||||
src += len;
|
||||
/* two's complement value: ~value + 1 */
|
||||
while (len-- != 0) {
|
||||
*(--dst) = (unsigned char)(carry += *(--src) ^ pad);
|
||||
carry >>= 8;
|
||||
}
|
||||
}
|
||||
|
||||
static size_t i2c_ibuf(const unsigned char *b, size_t blen, int neg,
|
||||
unsigned char **pp)
|
||||
{
|
||||
unsigned int pad = 0;
|
||||
size_t ret, i;
|
||||
unsigned char *p, pb = 0;
|
||||
|
||||
if (b != NULL && blen) {
|
||||
ret = blen;
|
||||
i = b[0];
|
||||
if (!neg && (i > 127)) {
|
||||
pad = 1;
|
||||
pb = 0;
|
||||
} else if (neg) {
|
||||
pb = 0xFF;
|
||||
if (i > 128) {
|
||||
pad = 1;
|
||||
} else if (i == 128) {
|
||||
/*
|
||||
* Special case [of minimal negative for given length]:
|
||||
* if any other bytes non zero we pad, otherwise we don't.
|
||||
*/
|
||||
for (pad = 0, i = 1; i < blen; i++)
|
||||
pad |= b[i];
|
||||
pb = pad != 0 ? 0xffU : 0;
|
||||
pad = pb & 1;
|
||||
}
|
||||
}
|
||||
ret += pad;
|
||||
} else {
|
||||
ret = 1;
|
||||
blen = 0; /* reduce '(b == NULL || blen == 0)' to '(blen == 0)' */
|
||||
}
|
||||
|
||||
if (pp == NULL || (p = *pp) == NULL)
|
||||
return ret;
|
||||
|
||||
/*
|
||||
* This magically handles all corner cases, such as '(b == NULL ||
|
||||
* blen == 0)', non-negative value, "negative" zero, 0x80 followed
|
||||
* by any number of zeros...
|
||||
*/
|
||||
*p = pb;
|
||||
p += pad; /* yes, p[0] can be written twice, but it's little
|
||||
* price to pay for eliminated branches */
|
||||
twos_complement(p, b, blen, pb);
|
||||
|
||||
*pp += ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* convert content octets into a big endian buffer. Returns the length
|
||||
* of buffer or 0 on error: for malformed INTEGER. If output buffer is
|
||||
* NULL just return length.
|
||||
*/
|
||||
|
||||
static size_t c2i_ibuf(unsigned char *b, int *pneg,
|
||||
const unsigned char *p, size_t plen)
|
||||
{
|
||||
int neg, pad;
|
||||
/* Zero content length is illegal */
|
||||
if (plen == 0) {
|
||||
ASN1err(ASN1_F_C2I_IBUF, ASN1_R_ILLEGAL_ZERO_CONTENT);
|
||||
return 0;
|
||||
}
|
||||
neg = p[0] & 0x80;
|
||||
if (pneg)
|
||||
*pneg = neg;
|
||||
/* Handle common case where length is 1 octet separately */
|
||||
if (plen == 1) {
|
||||
if (b != NULL) {
|
||||
if (neg)
|
||||
b[0] = (p[0] ^ 0xFF) + 1;
|
||||
else
|
||||
b[0] = p[0];
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
pad = 0;
|
||||
if (p[0] == 0) {
|
||||
pad = 1;
|
||||
} else if (p[0] == 0xFF) {
|
||||
size_t i;
|
||||
|
||||
/*
|
||||
* Special case [of "one less minimal negative" for given length]:
|
||||
* if any other bytes non zero it was padded, otherwise not.
|
||||
*/
|
||||
for (pad = 0, i = 1; i < plen; i++)
|
||||
pad |= p[i];
|
||||
pad = pad != 0 ? 1 : 0;
|
||||
}
|
||||
/* reject illegal padding: first two octets MSB can't match */
|
||||
if (pad && (neg == (p[1] & 0x80))) {
|
||||
ASN1err(ASN1_F_C2I_IBUF, ASN1_R_ILLEGAL_PADDING);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* skip over pad */
|
||||
p += pad;
|
||||
plen -= pad;
|
||||
|
||||
if (b != NULL)
|
||||
twos_complement(b, p, plen, neg ? 0xffU : 0);
|
||||
|
||||
return plen;
|
||||
}
|
||||
|
||||
int i2c_ASN1_INTEGER(ASN1_INTEGER *a, unsigned char **pp)
|
||||
{
|
||||
return i2c_ibuf(a->data, a->length, a->type & V_ASN1_NEG, pp);
|
||||
}
|
||||
|
||||
/* Convert big endian buffer into uint64_t, return 0 on error */
|
||||
static int asn1_get_uint64(uint64_t *pr, const unsigned char *b, size_t blen)
|
||||
{
|
||||
size_t i;
|
||||
uint64_t r;
|
||||
|
||||
if (blen > sizeof(*pr)) {
|
||||
ASN1err(ASN1_F_ASN1_GET_UINT64, ASN1_R_TOO_LARGE);
|
||||
return 0;
|
||||
}
|
||||
if (b == NULL)
|
||||
return 0;
|
||||
for (r = 0, i = 0; i < blen; i++) {
|
||||
r <<= 8;
|
||||
r |= b[i];
|
||||
}
|
||||
*pr = r;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Write uint64_t to big endian buffer and return offset to first
|
||||
* written octet. In other words it returns offset in range from 0
|
||||
* to 7, with 0 denoting 8 written octets and 7 - one.
|
||||
*/
|
||||
static size_t asn1_put_uint64(unsigned char b[sizeof(uint64_t)], uint64_t r)
|
||||
{
|
||||
size_t off = sizeof(uint64_t);
|
||||
|
||||
do {
|
||||
b[--off] = (unsigned char)r;
|
||||
} while (r >>= 8);
|
||||
|
||||
return off;
|
||||
}
|
||||
|
||||
/*
|
||||
* Absolute value of INT64_MIN: we can't just use -INT64_MIN as gcc produces
|
||||
* overflow warnings.
|
||||
*/
|
||||
#define ABS_INT64_MIN ((uint64_t)INT64_MAX + (-(INT64_MIN + INT64_MAX)))
|
||||
|
||||
/* signed version of asn1_get_uint64 */
|
||||
static int asn1_get_int64(int64_t *pr, const unsigned char *b, size_t blen,
|
||||
int neg)
|
||||
{
|
||||
uint64_t r;
|
||||
if (asn1_get_uint64(&r, b, blen) == 0)
|
||||
return 0;
|
||||
if (neg) {
|
||||
if (r <= INT64_MAX) {
|
||||
/* Most significant bit is guaranteed to be clear, negation
|
||||
* is guaranteed to be meaningful in platform-neutral sense. */
|
||||
*pr = -(int64_t)r;
|
||||
} else if (r == ABS_INT64_MIN) {
|
||||
/* This never happens if INT64_MAX == ABS_INT64_MIN, e.g.
|
||||
* on ones'-complement system. */
|
||||
*pr = (int64_t)(0 - r);
|
||||
} else {
|
||||
ASN1err(ASN1_F_ASN1_GET_INT64, ASN1_R_TOO_SMALL);
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
if (r <= INT64_MAX) {
|
||||
*pr = (int64_t)r;
|
||||
} else {
|
||||
ASN1err(ASN1_F_ASN1_GET_INT64, ASN1_R_TOO_LARGE);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Convert ASN1 INTEGER content octets to ASN1_INTEGER structure */
|
||||
ASN1_INTEGER *c2i_ASN1_INTEGER(ASN1_INTEGER **a, const unsigned char **pp,
|
||||
long len)
|
||||
{
|
||||
ASN1_INTEGER *ret = NULL;
|
||||
size_t r;
|
||||
int neg;
|
||||
|
||||
r = c2i_ibuf(NULL, NULL, *pp, len);
|
||||
|
||||
if (r == 0)
|
||||
return NULL;
|
||||
|
||||
if ((a == NULL) || ((*a) == NULL)) {
|
||||
ret = ASN1_INTEGER_new();
|
||||
if (ret == NULL)
|
||||
return NULL;
|
||||
ret->type = V_ASN1_INTEGER;
|
||||
} else
|
||||
ret = *a;
|
||||
|
||||
if (ASN1_STRING_set(ret, NULL, r) == 0)
|
||||
goto err;
|
||||
|
||||
c2i_ibuf(ret->data, &neg, *pp, len);
|
||||
|
||||
if (neg)
|
||||
ret->type |= V_ASN1_NEG;
|
||||
|
||||
*pp += len;
|
||||
if (a != NULL)
|
||||
(*a) = ret;
|
||||
return ret;
|
||||
err:
|
||||
ASN1err(ASN1_F_C2I_ASN1_INTEGER, ERR_R_MALLOC_FAILURE);
|
||||
if ((a == NULL) || (*a != ret))
|
||||
ASN1_INTEGER_free(ret);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int asn1_string_get_int64(int64_t *pr, const ASN1_STRING *a, int itype)
|
||||
{
|
||||
if (a == NULL) {
|
||||
ASN1err(ASN1_F_ASN1_STRING_GET_INT64, ERR_R_PASSED_NULL_PARAMETER);
|
||||
return 0;
|
||||
}
|
||||
if ((a->type & ~V_ASN1_NEG) != itype) {
|
||||
ASN1err(ASN1_F_ASN1_STRING_GET_INT64, ASN1_R_WRONG_INTEGER_TYPE);
|
||||
return 0;
|
||||
}
|
||||
return asn1_get_int64(pr, a->data, a->length, a->type & V_ASN1_NEG);
|
||||
}
|
||||
|
||||
static int asn1_string_set_int64(ASN1_STRING *a, int64_t r, int itype)
|
||||
{
|
||||
unsigned char tbuf[sizeof(r)];
|
||||
size_t off;
|
||||
|
||||
a->type = itype;
|
||||
if (r < 0) {
|
||||
/* Most obvious '-r' triggers undefined behaviour for most
|
||||
* common INT64_MIN. Even though below '0 - (uint64_t)r' can
|
||||
* appear two's-complement centric, it does produce correct/
|
||||
* expected result even on one's-complement. This is because
|
||||
* cast to unsigned has to change bit pattern... */
|
||||
off = asn1_put_uint64(tbuf, 0 - (uint64_t)r);
|
||||
a->type |= V_ASN1_NEG;
|
||||
} else {
|
||||
off = asn1_put_uint64(tbuf, r);
|
||||
a->type &= ~V_ASN1_NEG;
|
||||
}
|
||||
return ASN1_STRING_set(a, tbuf + off, sizeof(tbuf) - off);
|
||||
}
|
||||
|
||||
static int asn1_string_get_uint64(uint64_t *pr, const ASN1_STRING *a,
|
||||
int itype)
|
||||
{
|
||||
if (a == NULL) {
|
||||
ASN1err(ASN1_F_ASN1_STRING_GET_UINT64, ERR_R_PASSED_NULL_PARAMETER);
|
||||
return 0;
|
||||
}
|
||||
if ((a->type & ~V_ASN1_NEG) != itype) {
|
||||
ASN1err(ASN1_F_ASN1_STRING_GET_UINT64, ASN1_R_WRONG_INTEGER_TYPE);
|
||||
return 0;
|
||||
}
|
||||
if (a->type & V_ASN1_NEG) {
|
||||
ASN1err(ASN1_F_ASN1_STRING_GET_UINT64, ASN1_R_ILLEGAL_NEGATIVE_VALUE);
|
||||
return 0;
|
||||
}
|
||||
return asn1_get_uint64(pr, a->data, a->length);
|
||||
}
|
||||
|
||||
static int asn1_string_set_uint64(ASN1_STRING *a, uint64_t r, int itype)
|
||||
{
|
||||
unsigned char tbuf[sizeof(r)];
|
||||
size_t off;
|
||||
|
||||
a->type = itype;
|
||||
off = asn1_put_uint64(tbuf, r);
|
||||
return ASN1_STRING_set(a, tbuf + off, sizeof(tbuf) - off);
|
||||
}
|
||||
|
||||
/*
|
||||
* This is a version of d2i_ASN1_INTEGER that ignores the sign bit of ASN1
|
||||
* integers: some broken software can encode a positive INTEGER with its MSB
|
||||
* set as negative (it doesn't add a padding zero).
|
||||
*/
|
||||
|
||||
ASN1_INTEGER *d2i_ASN1_UINTEGER(ASN1_INTEGER **a, const unsigned char **pp,
|
||||
long length)
|
||||
{
|
||||
ASN1_INTEGER *ret = NULL;
|
||||
const unsigned char *p;
|
||||
unsigned char *s;
|
||||
long len;
|
||||
int inf, tag, xclass;
|
||||
int i;
|
||||
|
||||
if ((a == NULL) || ((*a) == NULL)) {
|
||||
if ((ret = ASN1_INTEGER_new()) == NULL)
|
||||
return NULL;
|
||||
ret->type = V_ASN1_INTEGER;
|
||||
} else
|
||||
ret = (*a);
|
||||
|
||||
p = *pp;
|
||||
inf = ASN1_get_object(&p, &len, &tag, &xclass, length);
|
||||
if (inf & 0x80) {
|
||||
i = ASN1_R_BAD_OBJECT_HEADER;
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (tag != V_ASN1_INTEGER) {
|
||||
i = ASN1_R_EXPECTING_AN_INTEGER;
|
||||
goto err;
|
||||
}
|
||||
|
||||
/*
|
||||
* We must OPENSSL_malloc stuff, even for 0 bytes otherwise it signifies
|
||||
* a missing NULL parameter.
|
||||
*/
|
||||
s = OPENSSL_malloc((int)len + 1);
|
||||
if (s == NULL) {
|
||||
i = ERR_R_MALLOC_FAILURE;
|
||||
goto err;
|
||||
}
|
||||
ret->type = V_ASN1_INTEGER;
|
||||
if (len) {
|
||||
if ((*p == 0) && (len != 1)) {
|
||||
p++;
|
||||
len--;
|
||||
}
|
||||
memcpy(s, p, (int)len);
|
||||
p += len;
|
||||
}
|
||||
|
||||
OPENSSL_free(ret->data);
|
||||
ret->data = s;
|
||||
ret->length = (int)len;
|
||||
if (a != NULL)
|
||||
(*a) = ret;
|
||||
*pp = p;
|
||||
return ret;
|
||||
err:
|
||||
ASN1err(ASN1_F_D2I_ASN1_UINTEGER, i);
|
||||
if ((a == NULL) || (*a != ret))
|
||||
ASN1_INTEGER_free(ret);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static ASN1_STRING *bn_to_asn1_string(const BIGNUM *bn, ASN1_STRING *ai,
|
||||
int atype)
|
||||
{
|
||||
ASN1_INTEGER *ret;
|
||||
int len;
|
||||
|
||||
if (ai == NULL) {
|
||||
ret = ASN1_STRING_type_new(atype);
|
||||
} else {
|
||||
ret = ai;
|
||||
ret->type = atype;
|
||||
}
|
||||
|
||||
if (ret == NULL) {
|
||||
ASN1err(ASN1_F_BN_TO_ASN1_STRING, ERR_R_NESTED_ASN1_ERROR);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (BN_is_negative(bn) && !BN_is_zero(bn))
|
||||
ret->type |= V_ASN1_NEG_INTEGER;
|
||||
|
||||
len = BN_num_bytes(bn);
|
||||
|
||||
if (len == 0)
|
||||
len = 1;
|
||||
|
||||
if (ASN1_STRING_set(ret, NULL, len) == 0) {
|
||||
ASN1err(ASN1_F_BN_TO_ASN1_STRING, ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Correct zero case */
|
||||
if (BN_is_zero(bn))
|
||||
ret->data[0] = 0;
|
||||
else
|
||||
len = BN_bn2bin(bn, ret->data);
|
||||
ret->length = len;
|
||||
return ret;
|
||||
err:
|
||||
if (ret != ai)
|
||||
ASN1_INTEGER_free(ret);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static BIGNUM *asn1_string_to_bn(const ASN1_INTEGER *ai, BIGNUM *bn,
|
||||
int itype)
|
||||
{
|
||||
BIGNUM *ret;
|
||||
|
||||
if ((ai->type & ~V_ASN1_NEG) != itype) {
|
||||
ASN1err(ASN1_F_ASN1_STRING_TO_BN, ASN1_R_WRONG_INTEGER_TYPE);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ret = BN_bin2bn(ai->data, ai->length, bn);
|
||||
if (ret == NULL) {
|
||||
ASN1err(ASN1_F_ASN1_STRING_TO_BN, ASN1_R_BN_LIB);
|
||||
return NULL;
|
||||
}
|
||||
if (ai->type & V_ASN1_NEG)
|
||||
BN_set_negative(ret, 1);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ASN1_INTEGER_get_int64(int64_t *pr, const ASN1_INTEGER *a)
|
||||
{
|
||||
return asn1_string_get_int64(pr, a, V_ASN1_INTEGER);
|
||||
}
|
||||
|
||||
int ASN1_INTEGER_set_int64(ASN1_INTEGER *a, int64_t r)
|
||||
{
|
||||
return asn1_string_set_int64(a, r, V_ASN1_INTEGER);
|
||||
}
|
||||
|
||||
int ASN1_INTEGER_get_uint64(uint64_t *pr, const ASN1_INTEGER *a)
|
||||
{
|
||||
return asn1_string_get_uint64(pr, a, V_ASN1_INTEGER);
|
||||
}
|
||||
|
||||
int ASN1_INTEGER_set_uint64(ASN1_INTEGER *a, uint64_t r)
|
||||
{
|
||||
return asn1_string_set_uint64(a, r, V_ASN1_INTEGER);
|
||||
}
|
||||
|
||||
int ASN1_INTEGER_set(ASN1_INTEGER *a, long v)
|
||||
{
|
||||
return ASN1_INTEGER_set_int64(a, v);
|
||||
}
|
||||
|
||||
long ASN1_INTEGER_get(const ASN1_INTEGER *a)
|
||||
{
|
||||
int i;
|
||||
int64_t r;
|
||||
if (a == NULL)
|
||||
return 0;
|
||||
i = ASN1_INTEGER_get_int64(&r, a);
|
||||
if (i == 0)
|
||||
return -1;
|
||||
if (r > LONG_MAX || r < LONG_MIN)
|
||||
return -1;
|
||||
return (long)r;
|
||||
}
|
||||
|
||||
ASN1_INTEGER *BN_to_ASN1_INTEGER(const BIGNUM *bn, ASN1_INTEGER *ai)
|
||||
{
|
||||
return bn_to_asn1_string(bn, ai, V_ASN1_INTEGER);
|
||||
}
|
||||
|
||||
BIGNUM *ASN1_INTEGER_to_BN(const ASN1_INTEGER *ai, BIGNUM *bn)
|
||||
{
|
||||
return asn1_string_to_bn(ai, bn, V_ASN1_INTEGER);
|
||||
}
|
||||
|
||||
int ASN1_ENUMERATED_get_int64(int64_t *pr, const ASN1_ENUMERATED *a)
|
||||
{
|
||||
return asn1_string_get_int64(pr, a, V_ASN1_ENUMERATED);
|
||||
}
|
||||
|
||||
int ASN1_ENUMERATED_set_int64(ASN1_ENUMERATED *a, int64_t r)
|
||||
{
|
||||
return asn1_string_set_int64(a, r, V_ASN1_ENUMERATED);
|
||||
}
|
||||
|
||||
int ASN1_ENUMERATED_set(ASN1_ENUMERATED *a, long v)
|
||||
{
|
||||
return ASN1_ENUMERATED_set_int64(a, v);
|
||||
}
|
||||
|
||||
long ASN1_ENUMERATED_get(const ASN1_ENUMERATED *a)
|
||||
{
|
||||
int i;
|
||||
int64_t r;
|
||||
if (a == NULL)
|
||||
return 0;
|
||||
if ((a->type & ~V_ASN1_NEG) != V_ASN1_ENUMERATED)
|
||||
return -1;
|
||||
if (a->length > (int)sizeof(long))
|
||||
return 0xffffffffL;
|
||||
i = ASN1_ENUMERATED_get_int64(&r, a);
|
||||
if (i == 0)
|
||||
return -1;
|
||||
if (r > LONG_MAX || r < LONG_MIN)
|
||||
return -1;
|
||||
return (long)r;
|
||||
}
|
||||
|
||||
ASN1_ENUMERATED *BN_to_ASN1_ENUMERATED(const BIGNUM *bn, ASN1_ENUMERATED *ai)
|
||||
{
|
||||
return bn_to_asn1_string(bn, ai, V_ASN1_ENUMERATED);
|
||||
}
|
||||
|
||||
BIGNUM *ASN1_ENUMERATED_to_BN(const ASN1_ENUMERATED *ai, BIGNUM *bn)
|
||||
{
|
||||
return asn1_string_to_bn(ai, bn, V_ASN1_ENUMERATED);
|
||||
}
|
||||
|
||||
/* Internal functions used by x_int64.c */
|
||||
int c2i_uint64_int(uint64_t *ret, int *neg, const unsigned char **pp, long len)
|
||||
{
|
||||
unsigned char buf[sizeof(uint64_t)];
|
||||
size_t buflen;
|
||||
|
||||
buflen = c2i_ibuf(NULL, NULL, *pp, len);
|
||||
if (buflen == 0)
|
||||
return 0;
|
||||
if (buflen > sizeof(uint64_t)) {
|
||||
ASN1err(ASN1_F_C2I_UINT64_INT, ASN1_R_TOO_LARGE);
|
||||
return 0;
|
||||
}
|
||||
(void)c2i_ibuf(buf, neg, *pp, len);
|
||||
return asn1_get_uint64(ret, buf, buflen);
|
||||
}
|
||||
|
||||
int i2c_uint64_int(unsigned char *p, uint64_t r, int neg)
|
||||
{
|
||||
unsigned char buf[sizeof(uint64_t)];
|
||||
size_t off;
|
||||
|
||||
off = asn1_put_uint64(buf, r);
|
||||
return i2c_ibuf(buf + off, sizeof(buf) - off, neg, &p);
|
||||
}
|
||||
|
||||
343
crypto/asn1/a_mbstr.c
Normal file
343
crypto/asn1/a_mbstr.c
Normal file
@@ -0,0 +1,343 @@
|
||||
/*
|
||||
* Copyright 1999-2017 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "internal/ctype.h"
|
||||
#include "internal/cryptlib.h"
|
||||
#include <openssl/asn1.h>
|
||||
|
||||
static int traverse_string(const unsigned char *p, int len, int inform,
|
||||
int (*rfunc) (unsigned long value, void *in),
|
||||
void *arg);
|
||||
static int in_utf8(unsigned long value, void *arg);
|
||||
static int out_utf8(unsigned long value, void *arg);
|
||||
static int type_str(unsigned long value, void *arg);
|
||||
static int cpy_asc(unsigned long value, void *arg);
|
||||
static int cpy_bmp(unsigned long value, void *arg);
|
||||
static int cpy_univ(unsigned long value, void *arg);
|
||||
static int cpy_utf8(unsigned long value, void *arg);
|
||||
|
||||
/*
|
||||
* These functions take a string in UTF8, ASCII or multibyte form and a mask
|
||||
* of permissible ASN1 string types. It then works out the minimal type
|
||||
* (using the order Numeric < Printable < IA5 < T61 < BMP < Universal < UTF8)
|
||||
* and creates a string of the correct type with the supplied data. Yes this is
|
||||
* horrible: it has to be :-( The 'ncopy' form checks minimum and maximum
|
||||
* size limits too.
|
||||
*/
|
||||
|
||||
int ASN1_mbstring_copy(ASN1_STRING **out, const unsigned char *in, int len,
|
||||
int inform, unsigned long mask)
|
||||
{
|
||||
return ASN1_mbstring_ncopy(out, in, len, inform, mask, 0, 0);
|
||||
}
|
||||
|
||||
int ASN1_mbstring_ncopy(ASN1_STRING **out, const unsigned char *in, int len,
|
||||
int inform, unsigned long mask,
|
||||
long minsize, long maxsize)
|
||||
{
|
||||
int str_type;
|
||||
int ret;
|
||||
char free_out;
|
||||
int outform, outlen = 0;
|
||||
ASN1_STRING *dest;
|
||||
unsigned char *p;
|
||||
int nchar;
|
||||
char strbuf[32];
|
||||
int (*cpyfunc) (unsigned long, void *) = NULL;
|
||||
if (len == -1)
|
||||
len = strlen((const char *)in);
|
||||
if (!mask)
|
||||
mask = DIRSTRING_TYPE;
|
||||
|
||||
/* First do a string check and work out the number of characters */
|
||||
switch (inform) {
|
||||
|
||||
case MBSTRING_BMP:
|
||||
if (len & 1) {
|
||||
ASN1err(ASN1_F_ASN1_MBSTRING_NCOPY,
|
||||
ASN1_R_INVALID_BMPSTRING_LENGTH);
|
||||
return -1;
|
||||
}
|
||||
nchar = len >> 1;
|
||||
break;
|
||||
|
||||
case MBSTRING_UNIV:
|
||||
if (len & 3) {
|
||||
ASN1err(ASN1_F_ASN1_MBSTRING_NCOPY,
|
||||
ASN1_R_INVALID_UNIVERSALSTRING_LENGTH);
|
||||
return -1;
|
||||
}
|
||||
nchar = len >> 2;
|
||||
break;
|
||||
|
||||
case MBSTRING_UTF8:
|
||||
nchar = 0;
|
||||
/* This counts the characters and does utf8 syntax checking */
|
||||
ret = traverse_string(in, len, MBSTRING_UTF8, in_utf8, &nchar);
|
||||
if (ret < 0) {
|
||||
ASN1err(ASN1_F_ASN1_MBSTRING_NCOPY, ASN1_R_INVALID_UTF8STRING);
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
|
||||
case MBSTRING_ASC:
|
||||
nchar = len;
|
||||
break;
|
||||
|
||||
default:
|
||||
ASN1err(ASN1_F_ASN1_MBSTRING_NCOPY, ASN1_R_UNKNOWN_FORMAT);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((minsize > 0) && (nchar < minsize)) {
|
||||
ASN1err(ASN1_F_ASN1_MBSTRING_NCOPY, ASN1_R_STRING_TOO_SHORT);
|
||||
BIO_snprintf(strbuf, sizeof(strbuf), "%ld", minsize);
|
||||
ERR_add_error_data(2, "minsize=", strbuf);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((maxsize > 0) && (nchar > maxsize)) {
|
||||
ASN1err(ASN1_F_ASN1_MBSTRING_NCOPY, ASN1_R_STRING_TOO_LONG);
|
||||
BIO_snprintf(strbuf, sizeof(strbuf), "%ld", maxsize);
|
||||
ERR_add_error_data(2, "maxsize=", strbuf);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Now work out minimal type (if any) */
|
||||
if (traverse_string(in, len, inform, type_str, &mask) < 0) {
|
||||
ASN1err(ASN1_F_ASN1_MBSTRING_NCOPY, ASN1_R_ILLEGAL_CHARACTERS);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Now work out output format and string type */
|
||||
outform = MBSTRING_ASC;
|
||||
if (mask & B_ASN1_NUMERICSTRING)
|
||||
str_type = V_ASN1_NUMERICSTRING;
|
||||
else if (mask & B_ASN1_PRINTABLESTRING)
|
||||
str_type = V_ASN1_PRINTABLESTRING;
|
||||
else if (mask & B_ASN1_IA5STRING)
|
||||
str_type = V_ASN1_IA5STRING;
|
||||
else if (mask & B_ASN1_T61STRING)
|
||||
str_type = V_ASN1_T61STRING;
|
||||
else if (mask & B_ASN1_BMPSTRING) {
|
||||
str_type = V_ASN1_BMPSTRING;
|
||||
outform = MBSTRING_BMP;
|
||||
} else if (mask & B_ASN1_UNIVERSALSTRING) {
|
||||
str_type = V_ASN1_UNIVERSALSTRING;
|
||||
outform = MBSTRING_UNIV;
|
||||
} else {
|
||||
str_type = V_ASN1_UTF8STRING;
|
||||
outform = MBSTRING_UTF8;
|
||||
}
|
||||
if (!out)
|
||||
return str_type;
|
||||
if (*out) {
|
||||
free_out = 0;
|
||||
dest = *out;
|
||||
OPENSSL_free(dest->data);
|
||||
dest->data = NULL;
|
||||
dest->length = 0;
|
||||
dest->type = str_type;
|
||||
} else {
|
||||
free_out = 1;
|
||||
dest = ASN1_STRING_type_new(str_type);
|
||||
if (dest == NULL) {
|
||||
ASN1err(ASN1_F_ASN1_MBSTRING_NCOPY, ERR_R_MALLOC_FAILURE);
|
||||
return -1;
|
||||
}
|
||||
*out = dest;
|
||||
}
|
||||
/* If both the same type just copy across */
|
||||
if (inform == outform) {
|
||||
if (!ASN1_STRING_set(dest, in, len)) {
|
||||
ASN1err(ASN1_F_ASN1_MBSTRING_NCOPY, ERR_R_MALLOC_FAILURE);
|
||||
return -1;
|
||||
}
|
||||
return str_type;
|
||||
}
|
||||
|
||||
/* Work out how much space the destination will need */
|
||||
switch (outform) {
|
||||
case MBSTRING_ASC:
|
||||
outlen = nchar;
|
||||
cpyfunc = cpy_asc;
|
||||
break;
|
||||
|
||||
case MBSTRING_BMP:
|
||||
outlen = nchar << 1;
|
||||
cpyfunc = cpy_bmp;
|
||||
break;
|
||||
|
||||
case MBSTRING_UNIV:
|
||||
outlen = nchar << 2;
|
||||
cpyfunc = cpy_univ;
|
||||
break;
|
||||
|
||||
case MBSTRING_UTF8:
|
||||
outlen = 0;
|
||||
traverse_string(in, len, inform, out_utf8, &outlen);
|
||||
cpyfunc = cpy_utf8;
|
||||
break;
|
||||
}
|
||||
if ((p = OPENSSL_malloc(outlen + 1)) == NULL) {
|
||||
if (free_out)
|
||||
ASN1_STRING_free(dest);
|
||||
ASN1err(ASN1_F_ASN1_MBSTRING_NCOPY, ERR_R_MALLOC_FAILURE);
|
||||
return -1;
|
||||
}
|
||||
dest->length = outlen;
|
||||
dest->data = p;
|
||||
p[outlen] = 0;
|
||||
traverse_string(in, len, inform, cpyfunc, &p);
|
||||
return str_type;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function traverses a string and passes the value of each character to
|
||||
* an optional function along with a void * argument.
|
||||
*/
|
||||
|
||||
static int traverse_string(const unsigned char *p, int len, int inform,
|
||||
int (*rfunc) (unsigned long value, void *in),
|
||||
void *arg)
|
||||
{
|
||||
unsigned long value;
|
||||
int ret;
|
||||
while (len) {
|
||||
if (inform == MBSTRING_ASC) {
|
||||
value = *p++;
|
||||
len--;
|
||||
} else if (inform == MBSTRING_BMP) {
|
||||
value = *p++ << 8;
|
||||
value |= *p++;
|
||||
len -= 2;
|
||||
} else if (inform == MBSTRING_UNIV) {
|
||||
value = ((unsigned long)*p++) << 24;
|
||||
value |= ((unsigned long)*p++) << 16;
|
||||
value |= *p++ << 8;
|
||||
value |= *p++;
|
||||
len -= 4;
|
||||
} else {
|
||||
ret = UTF8_getc(p, len, &value);
|
||||
if (ret < 0)
|
||||
return -1;
|
||||
len -= ret;
|
||||
p += ret;
|
||||
}
|
||||
if (rfunc) {
|
||||
ret = rfunc(value, arg);
|
||||
if (ret <= 0)
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Various utility functions for traverse_string */
|
||||
|
||||
/* Just count number of characters */
|
||||
|
||||
static int in_utf8(unsigned long value, void *arg)
|
||||
{
|
||||
int *nchar;
|
||||
nchar = arg;
|
||||
(*nchar)++;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Determine size of output as a UTF8 String */
|
||||
|
||||
static int out_utf8(unsigned long value, void *arg)
|
||||
{
|
||||
int *outlen;
|
||||
outlen = arg;
|
||||
*outlen += UTF8_putc(NULL, -1, value);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Determine the "type" of a string: check each character against a supplied
|
||||
* "mask".
|
||||
*/
|
||||
|
||||
static int type_str(unsigned long value, void *arg)
|
||||
{
|
||||
unsigned long types = *((unsigned long *)arg);
|
||||
const int native = value > INT_MAX ? INT_MAX : ossl_fromascii(value);
|
||||
|
||||
if ((types & B_ASN1_NUMERICSTRING) && !(ossl_isdigit(native)
|
||||
|| native == ' '))
|
||||
types &= ~B_ASN1_NUMERICSTRING;
|
||||
if ((types & B_ASN1_PRINTABLESTRING) && !ossl_isasn1print(native))
|
||||
types &= ~B_ASN1_PRINTABLESTRING;
|
||||
if ((types & B_ASN1_IA5STRING) && !ossl_isascii(native))
|
||||
types &= ~B_ASN1_IA5STRING;
|
||||
if ((types & B_ASN1_T61STRING) && (value > 0xff))
|
||||
types &= ~B_ASN1_T61STRING;
|
||||
if ((types & B_ASN1_BMPSTRING) && (value > 0xffff))
|
||||
types &= ~B_ASN1_BMPSTRING;
|
||||
if (!types)
|
||||
return -1;
|
||||
*((unsigned long *)arg) = types;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Copy one byte per character ASCII like strings */
|
||||
|
||||
static int cpy_asc(unsigned long value, void *arg)
|
||||
{
|
||||
unsigned char **p, *q;
|
||||
p = arg;
|
||||
q = *p;
|
||||
*q = (unsigned char)value;
|
||||
(*p)++;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Copy two byte per character BMPStrings */
|
||||
|
||||
static int cpy_bmp(unsigned long value, void *arg)
|
||||
{
|
||||
unsigned char **p, *q;
|
||||
p = arg;
|
||||
q = *p;
|
||||
*q++ = (unsigned char)((value >> 8) & 0xff);
|
||||
*q = (unsigned char)(value & 0xff);
|
||||
*p += 2;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Copy four byte per character UniversalStrings */
|
||||
|
||||
static int cpy_univ(unsigned long value, void *arg)
|
||||
{
|
||||
unsigned char **p, *q;
|
||||
p = arg;
|
||||
q = *p;
|
||||
*q++ = (unsigned char)((value >> 24) & 0xff);
|
||||
*q++ = (unsigned char)((value >> 16) & 0xff);
|
||||
*q++ = (unsigned char)((value >> 8) & 0xff);
|
||||
*q = (unsigned char)(value & 0xff);
|
||||
*p += 4;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Copy to a UTF8String */
|
||||
|
||||
static int cpy_utf8(unsigned long value, void *arg)
|
||||
{
|
||||
unsigned char **p;
|
||||
int ret;
|
||||
p = arg;
|
||||
/* We already know there is enough room so pass 0xff as the length */
|
||||
ret = UTF8_putc(*p, 0xff, value);
|
||||
*p += ret;
|
||||
return 1;
|
||||
}
|
||||
383
crypto/asn1/a_object.c
Normal file
383
crypto/asn1/a_object.c
Normal file
@@ -0,0 +1,383 @@
|
||||
/*
|
||||
* Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <limits.h>
|
||||
#include "internal/ctype.h"
|
||||
#include "internal/cryptlib.h"
|
||||
#include <openssl/buffer.h>
|
||||
#include <openssl/asn1.h>
|
||||
#include <openssl/objects.h>
|
||||
#include <openssl/bn.h>
|
||||
#include "internal/asn1_int.h"
|
||||
#include "asn1_locl.h"
|
||||
|
||||
int i2d_ASN1_OBJECT(const ASN1_OBJECT *a, unsigned char **pp)
|
||||
{
|
||||
unsigned char *p, *allocated = NULL;
|
||||
int objsize;
|
||||
|
||||
if ((a == NULL) || (a->data == NULL))
|
||||
return 0;
|
||||
|
||||
objsize = ASN1_object_size(0, a->length, V_ASN1_OBJECT);
|
||||
if (pp == NULL || objsize == -1)
|
||||
return objsize;
|
||||
|
||||
if (*pp == NULL) {
|
||||
if ((p = allocated = OPENSSL_malloc(objsize)) == NULL) {
|
||||
ASN1err(ASN1_F_I2D_ASN1_OBJECT, ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
p = *pp;
|
||||
}
|
||||
|
||||
ASN1_put_object(&p, 0, a->length, V_ASN1_OBJECT, V_ASN1_UNIVERSAL);
|
||||
memcpy(p, a->data, a->length);
|
||||
|
||||
/*
|
||||
* If a new buffer was allocated, just return it back.
|
||||
* If not, return the incremented buffer pointer.
|
||||
*/
|
||||
*pp = allocated != NULL ? allocated : p + a->length;
|
||||
return objsize;
|
||||
}
|
||||
|
||||
int a2d_ASN1_OBJECT(unsigned char *out, int olen, const char *buf, int num)
|
||||
{
|
||||
int i, first, len = 0, c, use_bn;
|
||||
char ftmp[24], *tmp = ftmp;
|
||||
int tmpsize = sizeof(ftmp);
|
||||
const char *p;
|
||||
unsigned long l;
|
||||
BIGNUM *bl = NULL;
|
||||
|
||||
if (num == 0)
|
||||
return 0;
|
||||
else if (num == -1)
|
||||
num = strlen(buf);
|
||||
|
||||
p = buf;
|
||||
c = *(p++);
|
||||
num--;
|
||||
if ((c >= '0') && (c <= '2')) {
|
||||
first = c - '0';
|
||||
} else {
|
||||
ASN1err(ASN1_F_A2D_ASN1_OBJECT, ASN1_R_FIRST_NUM_TOO_LARGE);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (num <= 0) {
|
||||
ASN1err(ASN1_F_A2D_ASN1_OBJECT, ASN1_R_MISSING_SECOND_NUMBER);
|
||||
goto err;
|
||||
}
|
||||
c = *(p++);
|
||||
num--;
|
||||
for (;;) {
|
||||
if (num <= 0)
|
||||
break;
|
||||
if ((c != '.') && (c != ' ')) {
|
||||
ASN1err(ASN1_F_A2D_ASN1_OBJECT, ASN1_R_INVALID_SEPARATOR);
|
||||
goto err;
|
||||
}
|
||||
l = 0;
|
||||
use_bn = 0;
|
||||
for (;;) {
|
||||
if (num <= 0)
|
||||
break;
|
||||
num--;
|
||||
c = *(p++);
|
||||
if ((c == ' ') || (c == '.'))
|
||||
break;
|
||||
if (!ossl_isdigit(c)) {
|
||||
ASN1err(ASN1_F_A2D_ASN1_OBJECT, ASN1_R_INVALID_DIGIT);
|
||||
goto err;
|
||||
}
|
||||
if (!use_bn && l >= ((ULONG_MAX - 80) / 10L)) {
|
||||
use_bn = 1;
|
||||
if (bl == NULL)
|
||||
bl = BN_new();
|
||||
if (bl == NULL || !BN_set_word(bl, l))
|
||||
goto err;
|
||||
}
|
||||
if (use_bn) {
|
||||
if (!BN_mul_word(bl, 10L)
|
||||
|| !BN_add_word(bl, c - '0'))
|
||||
goto err;
|
||||
} else
|
||||
l = l * 10L + (long)(c - '0');
|
||||
}
|
||||
if (len == 0) {
|
||||
if ((first < 2) && (l >= 40)) {
|
||||
ASN1err(ASN1_F_A2D_ASN1_OBJECT,
|
||||
ASN1_R_SECOND_NUMBER_TOO_LARGE);
|
||||
goto err;
|
||||
}
|
||||
if (use_bn) {
|
||||
if (!BN_add_word(bl, first * 40))
|
||||
goto err;
|
||||
} else
|
||||
l += (long)first *40;
|
||||
}
|
||||
i = 0;
|
||||
if (use_bn) {
|
||||
int blsize;
|
||||
blsize = BN_num_bits(bl);
|
||||
blsize = (blsize + 6) / 7;
|
||||
if (blsize > tmpsize) {
|
||||
if (tmp != ftmp)
|
||||
OPENSSL_free(tmp);
|
||||
tmpsize = blsize + 32;
|
||||
tmp = OPENSSL_malloc(tmpsize);
|
||||
if (tmp == NULL)
|
||||
goto err;
|
||||
}
|
||||
while (blsize--) {
|
||||
BN_ULONG t = BN_div_word(bl, 0x80L);
|
||||
if (t == (BN_ULONG)-1)
|
||||
goto err;
|
||||
tmp[i++] = (unsigned char)t;
|
||||
}
|
||||
} else {
|
||||
|
||||
for (;;) {
|
||||
tmp[i++] = (unsigned char)l & 0x7f;
|
||||
l >>= 7L;
|
||||
if (l == 0L)
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
if (out != NULL) {
|
||||
if (len + i > olen) {
|
||||
ASN1err(ASN1_F_A2D_ASN1_OBJECT, ASN1_R_BUFFER_TOO_SMALL);
|
||||
goto err;
|
||||
}
|
||||
while (--i > 0)
|
||||
out[len++] = tmp[i] | 0x80;
|
||||
out[len++] = tmp[0];
|
||||
} else
|
||||
len += i;
|
||||
}
|
||||
if (tmp != ftmp)
|
||||
OPENSSL_free(tmp);
|
||||
BN_free(bl);
|
||||
return len;
|
||||
err:
|
||||
if (tmp != ftmp)
|
||||
OPENSSL_free(tmp);
|
||||
BN_free(bl);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int i2t_ASN1_OBJECT(char *buf, int buf_len, const ASN1_OBJECT *a)
|
||||
{
|
||||
return OBJ_obj2txt(buf, buf_len, a, 0);
|
||||
}
|
||||
|
||||
int i2a_ASN1_OBJECT(BIO *bp, const ASN1_OBJECT *a)
|
||||
{
|
||||
char buf[80], *p = buf;
|
||||
int i;
|
||||
|
||||
if ((a == NULL) || (a->data == NULL))
|
||||
return BIO_write(bp, "NULL", 4);
|
||||
i = i2t_ASN1_OBJECT(buf, sizeof(buf), a);
|
||||
if (i > (int)(sizeof(buf) - 1)) {
|
||||
if ((p = OPENSSL_malloc(i + 1)) == NULL) {
|
||||
ASN1err(ASN1_F_I2A_ASN1_OBJECT, ERR_R_MALLOC_FAILURE);
|
||||
return -1;
|
||||
}
|
||||
i2t_ASN1_OBJECT(p, i + 1, a);
|
||||
}
|
||||
if (i <= 0) {
|
||||
i = BIO_write(bp, "<INVALID>", 9);
|
||||
i += BIO_dump(bp, (const char *)a->data, a->length);
|
||||
return i;
|
||||
}
|
||||
BIO_write(bp, p, i);
|
||||
if (p != buf)
|
||||
OPENSSL_free(p);
|
||||
return i;
|
||||
}
|
||||
|
||||
ASN1_OBJECT *d2i_ASN1_OBJECT(ASN1_OBJECT **a, const unsigned char **pp,
|
||||
long length)
|
||||
{
|
||||
const unsigned char *p;
|
||||
long len;
|
||||
int tag, xclass;
|
||||
int inf, i;
|
||||
ASN1_OBJECT *ret = NULL;
|
||||
p = *pp;
|
||||
inf = ASN1_get_object(&p, &len, &tag, &xclass, length);
|
||||
if (inf & 0x80) {
|
||||
i = ASN1_R_BAD_OBJECT_HEADER;
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (tag != V_ASN1_OBJECT) {
|
||||
i = ASN1_R_EXPECTING_AN_OBJECT;
|
||||
goto err;
|
||||
}
|
||||
ret = c2i_ASN1_OBJECT(a, &p, len);
|
||||
if (ret)
|
||||
*pp = p;
|
||||
return ret;
|
||||
err:
|
||||
ASN1err(ASN1_F_D2I_ASN1_OBJECT, i);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ASN1_OBJECT *c2i_ASN1_OBJECT(ASN1_OBJECT **a, const unsigned char **pp,
|
||||
long len)
|
||||
{
|
||||
ASN1_OBJECT *ret = NULL, tobj;
|
||||
const unsigned char *p;
|
||||
unsigned char *data;
|
||||
int i, length;
|
||||
|
||||
/*
|
||||
* Sanity check OID encoding. Need at least one content octet. MSB must
|
||||
* be clear in the last octet. can't have leading 0x80 in subidentifiers,
|
||||
* see: X.690 8.19.2
|
||||
*/
|
||||
if (len <= 0 || len > INT_MAX || pp == NULL || (p = *pp) == NULL ||
|
||||
p[len - 1] & 0x80) {
|
||||
ASN1err(ASN1_F_C2I_ASN1_OBJECT, ASN1_R_INVALID_OBJECT_ENCODING);
|
||||
return NULL;
|
||||
}
|
||||
/* Now 0 < len <= INT_MAX, so the cast is safe. */
|
||||
length = (int)len;
|
||||
/*
|
||||
* Try to lookup OID in table: these are all valid encodings so if we get
|
||||
* a match we know the OID is valid.
|
||||
*/
|
||||
tobj.nid = NID_undef;
|
||||
tobj.data = p;
|
||||
tobj.length = length;
|
||||
tobj.flags = 0;
|
||||
i = OBJ_obj2nid(&tobj);
|
||||
if (i != NID_undef) {
|
||||
/*
|
||||
* Return shared registered OID object: this improves efficiency
|
||||
* because we don't have to return a dynamically allocated OID
|
||||
* and NID lookups can use the cached value.
|
||||
*/
|
||||
ret = OBJ_nid2obj(i);
|
||||
if (a) {
|
||||
ASN1_OBJECT_free(*a);
|
||||
*a = ret;
|
||||
}
|
||||
*pp += len;
|
||||
return ret;
|
||||
}
|
||||
for (i = 0; i < length; i++, p++) {
|
||||
if (*p == 0x80 && (!i || !(p[-1] & 0x80))) {
|
||||
ASN1err(ASN1_F_C2I_ASN1_OBJECT, ASN1_R_INVALID_OBJECT_ENCODING);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* only the ASN1_OBJECTs from the 'table' will have values for ->sn or
|
||||
* ->ln
|
||||
*/
|
||||
if ((a == NULL) || ((*a) == NULL) ||
|
||||
!((*a)->flags & ASN1_OBJECT_FLAG_DYNAMIC)) {
|
||||
if ((ret = ASN1_OBJECT_new()) == NULL)
|
||||
return NULL;
|
||||
} else
|
||||
ret = (*a);
|
||||
|
||||
p = *pp;
|
||||
/* detach data from object */
|
||||
data = (unsigned char *)ret->data;
|
||||
ret->data = NULL;
|
||||
/* once detached we can change it */
|
||||
if ((data == NULL) || (ret->length < length)) {
|
||||
ret->length = 0;
|
||||
OPENSSL_free(data);
|
||||
data = OPENSSL_malloc(length);
|
||||
if (data == NULL) {
|
||||
i = ERR_R_MALLOC_FAILURE;
|
||||
goto err;
|
||||
}
|
||||
ret->flags |= ASN1_OBJECT_FLAG_DYNAMIC_DATA;
|
||||
}
|
||||
memcpy(data, p, length);
|
||||
/* reattach data to object, after which it remains const */
|
||||
ret->data = data;
|
||||
ret->length = length;
|
||||
ret->sn = NULL;
|
||||
ret->ln = NULL;
|
||||
/* ret->flags=ASN1_OBJECT_FLAG_DYNAMIC; we know it is dynamic */
|
||||
p += length;
|
||||
|
||||
if (a != NULL)
|
||||
(*a) = ret;
|
||||
*pp = p;
|
||||
return ret;
|
||||
err:
|
||||
ASN1err(ASN1_F_C2I_ASN1_OBJECT, i);
|
||||
if ((a == NULL) || (*a != ret))
|
||||
ASN1_OBJECT_free(ret);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ASN1_OBJECT *ASN1_OBJECT_new(void)
|
||||
{
|
||||
ASN1_OBJECT *ret;
|
||||
|
||||
ret = OPENSSL_zalloc(sizeof(*ret));
|
||||
if (ret == NULL) {
|
||||
ASN1err(ASN1_F_ASN1_OBJECT_NEW, ERR_R_MALLOC_FAILURE);
|
||||
return NULL;
|
||||
}
|
||||
ret->flags = ASN1_OBJECT_FLAG_DYNAMIC;
|
||||
return ret;
|
||||
}
|
||||
|
||||
void ASN1_OBJECT_free(ASN1_OBJECT *a)
|
||||
{
|
||||
if (a == NULL)
|
||||
return;
|
||||
if (a->flags & ASN1_OBJECT_FLAG_DYNAMIC_STRINGS) {
|
||||
#ifndef CONST_STRICT /* disable purely for compile-time strict
|
||||
* const checking. Doing this on a "real"
|
||||
* compile will cause memory leaks */
|
||||
OPENSSL_free((void*)a->sn);
|
||||
OPENSSL_free((void*)a->ln);
|
||||
#endif
|
||||
a->sn = a->ln = NULL;
|
||||
}
|
||||
if (a->flags & ASN1_OBJECT_FLAG_DYNAMIC_DATA) {
|
||||
OPENSSL_free((void*)a->data);
|
||||
a->data = NULL;
|
||||
a->length = 0;
|
||||
}
|
||||
if (a->flags & ASN1_OBJECT_FLAG_DYNAMIC)
|
||||
OPENSSL_free(a);
|
||||
}
|
||||
|
||||
ASN1_OBJECT *ASN1_OBJECT_create(int nid, unsigned char *data, int len,
|
||||
const char *sn, const char *ln)
|
||||
{
|
||||
ASN1_OBJECT o;
|
||||
|
||||
o.sn = sn;
|
||||
o.ln = ln;
|
||||
o.data = data;
|
||||
o.nid = nid;
|
||||
o.length = len;
|
||||
o.flags = ASN1_OBJECT_FLAG_DYNAMIC | ASN1_OBJECT_FLAG_DYNAMIC_STRINGS |
|
||||
ASN1_OBJECT_FLAG_DYNAMIC_DATA;
|
||||
return OBJ_dup(&o);
|
||||
}
|
||||
29
crypto/asn1/a_octet.c
Normal file
29
crypto/asn1/a_octet.c
Normal file
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "internal/cryptlib.h"
|
||||
#include <openssl/asn1.h>
|
||||
|
||||
ASN1_OCTET_STRING *ASN1_OCTET_STRING_dup(const ASN1_OCTET_STRING *x)
|
||||
{
|
||||
return ASN1_STRING_dup(x);
|
||||
}
|
||||
|
||||
int ASN1_OCTET_STRING_cmp(const ASN1_OCTET_STRING *a,
|
||||
const ASN1_OCTET_STRING *b)
|
||||
{
|
||||
return ASN1_STRING_cmp(a, b);
|
||||
}
|
||||
|
||||
int ASN1_OCTET_STRING_set(ASN1_OCTET_STRING *x, const unsigned char *d,
|
||||
int len)
|
||||
{
|
||||
return ASN1_STRING_set(x, d, len);
|
||||
}
|
||||
95
crypto/asn1/a_print.c
Normal file
95
crypto/asn1/a_print.c
Normal file
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
* Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "internal/ctype.h"
|
||||
#include "internal/cryptlib.h"
|
||||
#include <openssl/asn1.h>
|
||||
|
||||
int ASN1_PRINTABLE_type(const unsigned char *s, int len)
|
||||
{
|
||||
int c;
|
||||
int ia5 = 0;
|
||||
int t61 = 0;
|
||||
|
||||
if (len <= 0)
|
||||
len = -1;
|
||||
if (s == NULL)
|
||||
return V_ASN1_PRINTABLESTRING;
|
||||
|
||||
while ((*s) && (len-- != 0)) {
|
||||
c = *(s++);
|
||||
if (!ossl_isasn1print(c))
|
||||
ia5 = 1;
|
||||
if (!ossl_isascii(c))
|
||||
t61 = 1;
|
||||
}
|
||||
if (t61)
|
||||
return V_ASN1_T61STRING;
|
||||
if (ia5)
|
||||
return V_ASN1_IA5STRING;
|
||||
return V_ASN1_PRINTABLESTRING;
|
||||
}
|
||||
|
||||
int ASN1_UNIVERSALSTRING_to_string(ASN1_UNIVERSALSTRING *s)
|
||||
{
|
||||
int i;
|
||||
unsigned char *p;
|
||||
|
||||
if (s->type != V_ASN1_UNIVERSALSTRING)
|
||||
return 0;
|
||||
if ((s->length % 4) != 0)
|
||||
return 0;
|
||||
p = s->data;
|
||||
for (i = 0; i < s->length; i += 4) {
|
||||
if ((p[0] != '\0') || (p[1] != '\0') || (p[2] != '\0'))
|
||||
break;
|
||||
else
|
||||
p += 4;
|
||||
}
|
||||
if (i < s->length)
|
||||
return 0;
|
||||
p = s->data;
|
||||
for (i = 3; i < s->length; i += 4) {
|
||||
*(p++) = s->data[i];
|
||||
}
|
||||
*(p) = '\0';
|
||||
s->length /= 4;
|
||||
s->type = ASN1_PRINTABLE_type(s->data, s->length);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ASN1_STRING_print(BIO *bp, const ASN1_STRING *v)
|
||||
{
|
||||
int i, n;
|
||||
char buf[80];
|
||||
const char *p;
|
||||
|
||||
if (v == NULL)
|
||||
return 0;
|
||||
n = 0;
|
||||
p = (const char *)v->data;
|
||||
for (i = 0; i < v->length; i++) {
|
||||
if ((p[i] > '~') || ((p[i] < ' ') &&
|
||||
(p[i] != '\n') && (p[i] != '\r')))
|
||||
buf[n] = '.';
|
||||
else
|
||||
buf[n] = p[i];
|
||||
n++;
|
||||
if (n >= 80) {
|
||||
if (BIO_write(bp, buf, n) <= 0)
|
||||
return 0;
|
||||
n = 0;
|
||||
}
|
||||
}
|
||||
if (n > 0)
|
||||
if (BIO_write(bp, buf, n) <= 0)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
229
crypto/asn1/a_sign.c
Normal file
229
crypto/asn1/a_sign.c
Normal file
@@ -0,0 +1,229 @@
|
||||
/*
|
||||
* Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "internal/cryptlib.h"
|
||||
|
||||
#include <openssl/bn.h>
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/x509.h>
|
||||
#include <openssl/objects.h>
|
||||
#include <openssl/buffer.h>
|
||||
#include "internal/asn1_int.h"
|
||||
#include "internal/evp_int.h"
|
||||
|
||||
#ifndef NO_ASN1_OLD
|
||||
|
||||
int ASN1_sign(i2d_of_void *i2d, X509_ALGOR *algor1, X509_ALGOR *algor2,
|
||||
ASN1_BIT_STRING *signature, char *data, EVP_PKEY *pkey,
|
||||
const EVP_MD *type)
|
||||
{
|
||||
EVP_MD_CTX *ctx = EVP_MD_CTX_new();
|
||||
unsigned char *p, *buf_in = NULL, *buf_out = NULL;
|
||||
int i, inl = 0, outl = 0, outll = 0;
|
||||
X509_ALGOR *a;
|
||||
|
||||
if (ctx == NULL) {
|
||||
ASN1err(ASN1_F_ASN1_SIGN, ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
for (i = 0; i < 2; i++) {
|
||||
if (i == 0)
|
||||
a = algor1;
|
||||
else
|
||||
a = algor2;
|
||||
if (a == NULL)
|
||||
continue;
|
||||
if (type->pkey_type == NID_dsaWithSHA1) {
|
||||
/*
|
||||
* special case: RFC 2459 tells us to omit 'parameters' with
|
||||
* id-dsa-with-sha1
|
||||
*/
|
||||
ASN1_TYPE_free(a->parameter);
|
||||
a->parameter = NULL;
|
||||
} else if ((a->parameter == NULL) ||
|
||||
(a->parameter->type != V_ASN1_NULL)) {
|
||||
ASN1_TYPE_free(a->parameter);
|
||||
if ((a->parameter = ASN1_TYPE_new()) == NULL)
|
||||
goto err;
|
||||
a->parameter->type = V_ASN1_NULL;
|
||||
}
|
||||
ASN1_OBJECT_free(a->algorithm);
|
||||
a->algorithm = OBJ_nid2obj(type->pkey_type);
|
||||
if (a->algorithm == NULL) {
|
||||
ASN1err(ASN1_F_ASN1_SIGN, ASN1_R_UNKNOWN_OBJECT_TYPE);
|
||||
goto err;
|
||||
}
|
||||
if (a->algorithm->length == 0) {
|
||||
ASN1err(ASN1_F_ASN1_SIGN,
|
||||
ASN1_R_THE_ASN1_OBJECT_IDENTIFIER_IS_NOT_KNOWN_FOR_THIS_MD);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
inl = i2d(data, NULL);
|
||||
buf_in = OPENSSL_malloc((unsigned int)inl);
|
||||
outll = outl = EVP_PKEY_size(pkey);
|
||||
buf_out = OPENSSL_malloc((unsigned int)outl);
|
||||
if ((buf_in == NULL) || (buf_out == NULL)) {
|
||||
outl = 0;
|
||||
ASN1err(ASN1_F_ASN1_SIGN, ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
p = buf_in;
|
||||
|
||||
i2d(data, &p);
|
||||
if (!EVP_SignInit_ex(ctx, type, NULL)
|
||||
|| !EVP_SignUpdate(ctx, (unsigned char *)buf_in, inl)
|
||||
|| !EVP_SignFinal(ctx, (unsigned char *)buf_out,
|
||||
(unsigned int *)&outl, pkey)) {
|
||||
outl = 0;
|
||||
ASN1err(ASN1_F_ASN1_SIGN, ERR_R_EVP_LIB);
|
||||
goto err;
|
||||
}
|
||||
OPENSSL_free(signature->data);
|
||||
signature->data = buf_out;
|
||||
buf_out = NULL;
|
||||
signature->length = outl;
|
||||
/*
|
||||
* In the interests of compatibility, I'll make sure that the bit string
|
||||
* has a 'not-used bits' value of 0
|
||||
*/
|
||||
signature->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07);
|
||||
signature->flags |= ASN1_STRING_FLAG_BITS_LEFT;
|
||||
err:
|
||||
EVP_MD_CTX_free(ctx);
|
||||
OPENSSL_clear_free((char *)buf_in, (unsigned int)inl);
|
||||
OPENSSL_clear_free((char *)buf_out, outll);
|
||||
return outl;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
int ASN1_item_sign(const ASN1_ITEM *it, X509_ALGOR *algor1,
|
||||
X509_ALGOR *algor2, ASN1_BIT_STRING *signature, void *asn,
|
||||
EVP_PKEY *pkey, const EVP_MD *type)
|
||||
{
|
||||
int rv;
|
||||
EVP_MD_CTX *ctx = EVP_MD_CTX_new();
|
||||
|
||||
if (ctx == NULL) {
|
||||
ASN1err(ASN1_F_ASN1_ITEM_SIGN, ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
if (!EVP_DigestSignInit(ctx, NULL, type, NULL, pkey)) {
|
||||
EVP_MD_CTX_free(ctx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
rv = ASN1_item_sign_ctx(it, algor1, algor2, signature, asn, ctx);
|
||||
|
||||
EVP_MD_CTX_free(ctx);
|
||||
return rv;
|
||||
}
|
||||
|
||||
int ASN1_item_sign_ctx(const ASN1_ITEM *it,
|
||||
X509_ALGOR *algor1, X509_ALGOR *algor2,
|
||||
ASN1_BIT_STRING *signature, void *asn, EVP_MD_CTX *ctx)
|
||||
{
|
||||
const EVP_MD *type;
|
||||
EVP_PKEY *pkey;
|
||||
unsigned char *buf_in = NULL, *buf_out = NULL;
|
||||
size_t inl = 0, outl = 0, outll = 0;
|
||||
int signid, paramtype;
|
||||
int rv;
|
||||
|
||||
type = EVP_MD_CTX_md(ctx);
|
||||
pkey = EVP_PKEY_CTX_get0_pkey(EVP_MD_CTX_pkey_ctx(ctx));
|
||||
|
||||
if (pkey == NULL) {
|
||||
ASN1err(ASN1_F_ASN1_ITEM_SIGN_CTX, ASN1_R_CONTEXT_NOT_INITIALISED);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (pkey->ameth == NULL) {
|
||||
ASN1err(ASN1_F_ASN1_ITEM_SIGN_CTX, ASN1_R_DIGEST_AND_KEY_TYPE_NOT_SUPPORTED);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (pkey->ameth->item_sign) {
|
||||
rv = pkey->ameth->item_sign(ctx, it, asn, algor1, algor2, signature);
|
||||
if (rv == 1)
|
||||
outl = signature->length;
|
||||
/*-
|
||||
* Return value meanings:
|
||||
* <=0: error.
|
||||
* 1: method does everything.
|
||||
* 2: carry on as normal.
|
||||
* 3: ASN1 method sets algorithm identifiers: just sign.
|
||||
*/
|
||||
if (rv <= 0)
|
||||
ASN1err(ASN1_F_ASN1_ITEM_SIGN_CTX, ERR_R_EVP_LIB);
|
||||
if (rv <= 1)
|
||||
goto err;
|
||||
} else {
|
||||
rv = 2;
|
||||
}
|
||||
|
||||
if (rv == 2) {
|
||||
if (type == NULL) {
|
||||
ASN1err(ASN1_F_ASN1_ITEM_SIGN_CTX, ASN1_R_CONTEXT_NOT_INITIALISED);
|
||||
goto err;
|
||||
}
|
||||
if (!OBJ_find_sigid_by_algs(&signid,
|
||||
EVP_MD_nid(type),
|
||||
pkey->ameth->pkey_id)) {
|
||||
ASN1err(ASN1_F_ASN1_ITEM_SIGN_CTX,
|
||||
ASN1_R_DIGEST_AND_KEY_TYPE_NOT_SUPPORTED);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (pkey->ameth->pkey_flags & ASN1_PKEY_SIGPARAM_NULL)
|
||||
paramtype = V_ASN1_NULL;
|
||||
else
|
||||
paramtype = V_ASN1_UNDEF;
|
||||
|
||||
if (algor1)
|
||||
X509_ALGOR_set0(algor1, OBJ_nid2obj(signid), paramtype, NULL);
|
||||
if (algor2)
|
||||
X509_ALGOR_set0(algor2, OBJ_nid2obj(signid), paramtype, NULL);
|
||||
|
||||
}
|
||||
|
||||
inl = ASN1_item_i2d(asn, &buf_in, it);
|
||||
outll = outl = EVP_PKEY_size(pkey);
|
||||
buf_out = OPENSSL_malloc((unsigned int)outl);
|
||||
if ((buf_in == NULL) || (buf_out == NULL)) {
|
||||
outl = 0;
|
||||
ASN1err(ASN1_F_ASN1_ITEM_SIGN_CTX, ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!EVP_DigestSign(ctx, buf_out, &outl, buf_in, inl)) {
|
||||
outl = 0;
|
||||
ASN1err(ASN1_F_ASN1_ITEM_SIGN_CTX, ERR_R_EVP_LIB);
|
||||
goto err;
|
||||
}
|
||||
OPENSSL_free(signature->data);
|
||||
signature->data = buf_out;
|
||||
buf_out = NULL;
|
||||
signature->length = outl;
|
||||
/*
|
||||
* In the interests of compatibility, I'll make sure that the bit string
|
||||
* has a 'not-used bits' value of 0
|
||||
*/
|
||||
signature->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07);
|
||||
signature->flags |= ASN1_STRING_FLAG_BITS_LEFT;
|
||||
err:
|
||||
OPENSSL_clear_free((char *)buf_in, (unsigned int)inl);
|
||||
OPENSSL_clear_free((char *)buf_out, outll);
|
||||
return outl;
|
||||
}
|
||||
626
crypto/asn1/a_strex.c
Normal file
626
crypto/asn1/a_strex.c
Normal file
@@ -0,0 +1,626 @@
|
||||
/*
|
||||
* Copyright 2000-2018 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "internal/cryptlib.h"
|
||||
#include "internal/asn1_int.h"
|
||||
#include <openssl/crypto.h>
|
||||
#include <openssl/x509.h>
|
||||
#include <openssl/asn1.h>
|
||||
|
||||
#include "charmap.h"
|
||||
|
||||
/*
|
||||
* ASN1_STRING_print_ex() and X509_NAME_print_ex(). Enhanced string and name
|
||||
* printing routines handling multibyte characters, RFC2253 and a host of
|
||||
* other options.
|
||||
*/
|
||||
|
||||
#define CHARTYPE_BS_ESC (ASN1_STRFLGS_ESC_2253 | CHARTYPE_FIRST_ESC_2253 | CHARTYPE_LAST_ESC_2253)
|
||||
|
||||
#define ESC_FLAGS (ASN1_STRFLGS_ESC_2253 | \
|
||||
ASN1_STRFLGS_ESC_2254 | \
|
||||
ASN1_STRFLGS_ESC_QUOTE | \
|
||||
ASN1_STRFLGS_ESC_CTRL | \
|
||||
ASN1_STRFLGS_ESC_MSB)
|
||||
|
||||
/*
|
||||
* Three IO functions for sending data to memory, a BIO and and a FILE
|
||||
* pointer.
|
||||
*/
|
||||
static int send_bio_chars(void *arg, const void *buf, int len)
|
||||
{
|
||||
if (!arg)
|
||||
return 1;
|
||||
if (BIO_write(arg, buf, len) != len)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
#ifndef OPENSSL_NO_STDIO
|
||||
static int send_fp_chars(void *arg, const void *buf, int len)
|
||||
{
|
||||
if (!arg)
|
||||
return 1;
|
||||
if (fwrite(buf, 1, len, arg) != (unsigned int)len)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
typedef int char_io (void *arg, const void *buf, int len);
|
||||
|
||||
/*
|
||||
* This function handles display of strings, one character at a time. It is
|
||||
* passed an unsigned long for each character because it could come from 2 or
|
||||
* even 4 byte forms.
|
||||
*/
|
||||
|
||||
static int do_esc_char(unsigned long c, unsigned short flags, char *do_quotes,
|
||||
char_io *io_ch, void *arg)
|
||||
{
|
||||
unsigned short chflgs;
|
||||
unsigned char chtmp;
|
||||
char tmphex[HEX_SIZE(long) + 3];
|
||||
|
||||
if (c > 0xffffffffL)
|
||||
return -1;
|
||||
if (c > 0xffff) {
|
||||
BIO_snprintf(tmphex, sizeof(tmphex), "\\W%08lX", c);
|
||||
if (!io_ch(arg, tmphex, 10))
|
||||
return -1;
|
||||
return 10;
|
||||
}
|
||||
if (c > 0xff) {
|
||||
BIO_snprintf(tmphex, sizeof(tmphex), "\\U%04lX", c);
|
||||
if (!io_ch(arg, tmphex, 6))
|
||||
return -1;
|
||||
return 6;
|
||||
}
|
||||
chtmp = (unsigned char)c;
|
||||
if (chtmp > 0x7f)
|
||||
chflgs = flags & ASN1_STRFLGS_ESC_MSB;
|
||||
else
|
||||
chflgs = char_type[chtmp] & flags;
|
||||
if (chflgs & CHARTYPE_BS_ESC) {
|
||||
/* If we don't escape with quotes, signal we need quotes */
|
||||
if (chflgs & ASN1_STRFLGS_ESC_QUOTE) {
|
||||
if (do_quotes)
|
||||
*do_quotes = 1;
|
||||
if (!io_ch(arg, &chtmp, 1))
|
||||
return -1;
|
||||
return 1;
|
||||
}
|
||||
if (!io_ch(arg, "\\", 1))
|
||||
return -1;
|
||||
if (!io_ch(arg, &chtmp, 1))
|
||||
return -1;
|
||||
return 2;
|
||||
}
|
||||
if (chflgs & (ASN1_STRFLGS_ESC_CTRL
|
||||
| ASN1_STRFLGS_ESC_MSB
|
||||
| ASN1_STRFLGS_ESC_2254)) {
|
||||
BIO_snprintf(tmphex, 11, "\\%02X", chtmp);
|
||||
if (!io_ch(arg, tmphex, 3))
|
||||
return -1;
|
||||
return 3;
|
||||
}
|
||||
/*
|
||||
* If we get this far and do any escaping at all must escape the escape
|
||||
* character itself: backslash.
|
||||
*/
|
||||
if (chtmp == '\\' && (flags & ESC_FLAGS)) {
|
||||
if (!io_ch(arg, "\\\\", 2))
|
||||
return -1;
|
||||
return 2;
|
||||
}
|
||||
if (!io_ch(arg, &chtmp, 1))
|
||||
return -1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
#define BUF_TYPE_WIDTH_MASK 0x7
|
||||
#define BUF_TYPE_CONVUTF8 0x8
|
||||
|
||||
/*
|
||||
* This function sends each character in a buffer to do_esc_char(). It
|
||||
* interprets the content formats and converts to or from UTF8 as
|
||||
* appropriate.
|
||||
*/
|
||||
|
||||
static int do_buf(unsigned char *buf, int buflen,
|
||||
int type, unsigned short flags, char *quotes, char_io *io_ch,
|
||||
void *arg)
|
||||
{
|
||||
int i, outlen, len, charwidth;
|
||||
unsigned short orflags;
|
||||
unsigned char *p, *q;
|
||||
unsigned long c;
|
||||
|
||||
p = buf;
|
||||
q = buf + buflen;
|
||||
outlen = 0;
|
||||
charwidth = type & BUF_TYPE_WIDTH_MASK;
|
||||
|
||||
switch (charwidth) {
|
||||
case 4:
|
||||
if (buflen & 3) {
|
||||
ASN1err(ASN1_F_DO_BUF, ASN1_R_INVALID_UNIVERSALSTRING_LENGTH);
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
if (buflen & 1) {
|
||||
ASN1err(ASN1_F_DO_BUF, ASN1_R_INVALID_BMPSTRING_LENGTH);
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
while (p != q) {
|
||||
if (p == buf && flags & ASN1_STRFLGS_ESC_2253)
|
||||
orflags = CHARTYPE_FIRST_ESC_2253;
|
||||
else
|
||||
orflags = 0;
|
||||
|
||||
switch (charwidth) {
|
||||
case 4:
|
||||
c = ((unsigned long)*p++) << 24;
|
||||
c |= ((unsigned long)*p++) << 16;
|
||||
c |= ((unsigned long)*p++) << 8;
|
||||
c |= *p++;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
c = ((unsigned long)*p++) << 8;
|
||||
c |= *p++;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
c = *p++;
|
||||
break;
|
||||
|
||||
case 0:
|
||||
i = UTF8_getc(p, buflen, &c);
|
||||
if (i < 0)
|
||||
return -1; /* Invalid UTF8String */
|
||||
buflen -= i;
|
||||
p += i;
|
||||
break;
|
||||
default:
|
||||
return -1; /* invalid width */
|
||||
}
|
||||
if (p == q && flags & ASN1_STRFLGS_ESC_2253)
|
||||
orflags = CHARTYPE_LAST_ESC_2253;
|
||||
if (type & BUF_TYPE_CONVUTF8) {
|
||||
unsigned char utfbuf[6];
|
||||
int utflen;
|
||||
utflen = UTF8_putc(utfbuf, sizeof(utfbuf), c);
|
||||
for (i = 0; i < utflen; i++) {
|
||||
/*
|
||||
* We don't need to worry about setting orflags correctly
|
||||
* because if utflen==1 its value will be correct anyway
|
||||
* otherwise each character will be > 0x7f and so the
|
||||
* character will never be escaped on first and last.
|
||||
*/
|
||||
len = do_esc_char(utfbuf[i], flags | orflags, quotes,
|
||||
io_ch, arg);
|
||||
if (len < 0)
|
||||
return -1;
|
||||
outlen += len;
|
||||
}
|
||||
} else {
|
||||
len = do_esc_char(c, flags | orflags, quotes,
|
||||
io_ch, arg);
|
||||
if (len < 0)
|
||||
return -1;
|
||||
outlen += len;
|
||||
}
|
||||
}
|
||||
return outlen;
|
||||
}
|
||||
|
||||
/* This function hex dumps a buffer of characters */
|
||||
|
||||
static int do_hex_dump(char_io *io_ch, void *arg, unsigned char *buf,
|
||||
int buflen)
|
||||
{
|
||||
static const char hexdig[] = "0123456789ABCDEF";
|
||||
unsigned char *p, *q;
|
||||
char hextmp[2];
|
||||
if (arg) {
|
||||
p = buf;
|
||||
q = buf + buflen;
|
||||
while (p != q) {
|
||||
hextmp[0] = hexdig[*p >> 4];
|
||||
hextmp[1] = hexdig[*p & 0xf];
|
||||
if (!io_ch(arg, hextmp, 2))
|
||||
return -1;
|
||||
p++;
|
||||
}
|
||||
}
|
||||
return buflen << 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* "dump" a string. This is done when the type is unknown, or the flags
|
||||
* request it. We can either dump the content octets or the entire DER
|
||||
* encoding. This uses the RFC2253 #01234 format.
|
||||
*/
|
||||
|
||||
static int do_dump(unsigned long lflags, char_io *io_ch, void *arg,
|
||||
const ASN1_STRING *str)
|
||||
{
|
||||
/*
|
||||
* Placing the ASN1_STRING in a temp ASN1_TYPE allows the DER encoding to
|
||||
* readily obtained
|
||||
*/
|
||||
ASN1_TYPE t;
|
||||
unsigned char *der_buf, *p;
|
||||
int outlen, der_len;
|
||||
|
||||
if (!io_ch(arg, "#", 1))
|
||||
return -1;
|
||||
/* If we don't dump DER encoding just dump content octets */
|
||||
if (!(lflags & ASN1_STRFLGS_DUMP_DER)) {
|
||||
outlen = do_hex_dump(io_ch, arg, str->data, str->length);
|
||||
if (outlen < 0)
|
||||
return -1;
|
||||
return outlen + 1;
|
||||
}
|
||||
t.type = str->type;
|
||||
t.value.ptr = (char *)str;
|
||||
der_len = i2d_ASN1_TYPE(&t, NULL);
|
||||
if ((der_buf = OPENSSL_malloc(der_len)) == NULL) {
|
||||
ASN1err(ASN1_F_DO_DUMP, ERR_R_MALLOC_FAILURE);
|
||||
return -1;
|
||||
}
|
||||
p = der_buf;
|
||||
i2d_ASN1_TYPE(&t, &p);
|
||||
outlen = do_hex_dump(io_ch, arg, der_buf, der_len);
|
||||
OPENSSL_free(der_buf);
|
||||
if (outlen < 0)
|
||||
return -1;
|
||||
return outlen + 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Lookup table to convert tags to character widths, 0 = UTF8 encoded, -1 is
|
||||
* used for non string types otherwise it is the number of bytes per
|
||||
* character
|
||||
*/
|
||||
|
||||
static const signed char tag2nbyte[] = {
|
||||
-1, -1, -1, -1, -1, /* 0-4 */
|
||||
-1, -1, -1, -1, -1, /* 5-9 */
|
||||
-1, -1, /* 10-11 */
|
||||
0, /* 12 V_ASN1_UTF8STRING */
|
||||
-1, -1, -1, -1, -1, /* 13-17 */
|
||||
1, /* 18 V_ASN1_NUMERICSTRING */
|
||||
1, /* 19 V_ASN1_PRINTABLESTRING */
|
||||
1, /* 20 V_ASN1_T61STRING */
|
||||
-1, /* 21 */
|
||||
1, /* 22 V_ASN1_IA5STRING */
|
||||
1, /* 23 V_ASN1_UTCTIME */
|
||||
1, /* 24 V_ASN1_GENERALIZEDTIME */
|
||||
-1, /* 25 */
|
||||
1, /* 26 V_ASN1_ISO64STRING */
|
||||
-1, /* 27 */
|
||||
4, /* 28 V_ASN1_UNIVERSALSTRING */
|
||||
-1, /* 29 */
|
||||
2 /* 30 V_ASN1_BMPSTRING */
|
||||
};
|
||||
|
||||
/*
|
||||
* This is the main function, print out an ASN1_STRING taking note of various
|
||||
* escape and display options. Returns number of characters written or -1 if
|
||||
* an error occurred.
|
||||
*/
|
||||
|
||||
static int do_print_ex(char_io *io_ch, void *arg, unsigned long lflags,
|
||||
const ASN1_STRING *str)
|
||||
{
|
||||
int outlen, len;
|
||||
int type;
|
||||
char quotes;
|
||||
unsigned short flags;
|
||||
quotes = 0;
|
||||
/* Keep a copy of escape flags */
|
||||
flags = (unsigned short)(lflags & ESC_FLAGS);
|
||||
|
||||
type = str->type;
|
||||
|
||||
outlen = 0;
|
||||
|
||||
if (lflags & ASN1_STRFLGS_SHOW_TYPE) {
|
||||
const char *tagname;
|
||||
tagname = ASN1_tag2str(type);
|
||||
outlen += strlen(tagname);
|
||||
if (!io_ch(arg, tagname, outlen) || !io_ch(arg, ":", 1))
|
||||
return -1;
|
||||
outlen++;
|
||||
}
|
||||
|
||||
/* Decide what to do with type, either dump content or display it */
|
||||
|
||||
/* Dump everything */
|
||||
if (lflags & ASN1_STRFLGS_DUMP_ALL)
|
||||
type = -1;
|
||||
/* Ignore the string type */
|
||||
else if (lflags & ASN1_STRFLGS_IGNORE_TYPE)
|
||||
type = 1;
|
||||
else {
|
||||
/* Else determine width based on type */
|
||||
if ((type > 0) && (type < 31))
|
||||
type = tag2nbyte[type];
|
||||
else
|
||||
type = -1;
|
||||
if ((type == -1) && !(lflags & ASN1_STRFLGS_DUMP_UNKNOWN))
|
||||
type = 1;
|
||||
}
|
||||
|
||||
if (type == -1) {
|
||||
len = do_dump(lflags, io_ch, arg, str);
|
||||
if (len < 0)
|
||||
return -1;
|
||||
outlen += len;
|
||||
return outlen;
|
||||
}
|
||||
|
||||
if (lflags & ASN1_STRFLGS_UTF8_CONVERT) {
|
||||
/*
|
||||
* Note: if string is UTF8 and we want to convert to UTF8 then we
|
||||
* just interpret it as 1 byte per character to avoid converting
|
||||
* twice.
|
||||
*/
|
||||
if (!type)
|
||||
type = 1;
|
||||
else
|
||||
type |= BUF_TYPE_CONVUTF8;
|
||||
}
|
||||
|
||||
len = do_buf(str->data, str->length, type, flags, "es, io_ch, NULL);
|
||||
if (len < 0)
|
||||
return -1;
|
||||
outlen += len;
|
||||
if (quotes)
|
||||
outlen += 2;
|
||||
if (!arg)
|
||||
return outlen;
|
||||
if (quotes && !io_ch(arg, "\"", 1))
|
||||
return -1;
|
||||
if (do_buf(str->data, str->length, type, flags, NULL, io_ch, arg) < 0)
|
||||
return -1;
|
||||
if (quotes && !io_ch(arg, "\"", 1))
|
||||
return -1;
|
||||
return outlen;
|
||||
}
|
||||
|
||||
/* Used for line indenting: print 'indent' spaces */
|
||||
|
||||
static int do_indent(char_io *io_ch, void *arg, int indent)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < indent; i++)
|
||||
if (!io_ch(arg, " ", 1))
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
#define FN_WIDTH_LN 25
|
||||
#define FN_WIDTH_SN 10
|
||||
|
||||
static int do_name_ex(char_io *io_ch, void *arg, const X509_NAME *n,
|
||||
int indent, unsigned long flags)
|
||||
{
|
||||
int i, prev = -1, orflags, cnt;
|
||||
int fn_opt, fn_nid;
|
||||
ASN1_OBJECT *fn;
|
||||
const ASN1_STRING *val;
|
||||
const X509_NAME_ENTRY *ent;
|
||||
char objtmp[80];
|
||||
const char *objbuf;
|
||||
int outlen, len;
|
||||
char *sep_dn, *sep_mv, *sep_eq;
|
||||
int sep_dn_len, sep_mv_len, sep_eq_len;
|
||||
if (indent < 0)
|
||||
indent = 0;
|
||||
outlen = indent;
|
||||
if (!do_indent(io_ch, arg, indent))
|
||||
return -1;
|
||||
switch (flags & XN_FLAG_SEP_MASK) {
|
||||
case XN_FLAG_SEP_MULTILINE:
|
||||
sep_dn = "\n";
|
||||
sep_dn_len = 1;
|
||||
sep_mv = " + ";
|
||||
sep_mv_len = 3;
|
||||
break;
|
||||
|
||||
case XN_FLAG_SEP_COMMA_PLUS:
|
||||
sep_dn = ",";
|
||||
sep_dn_len = 1;
|
||||
sep_mv = "+";
|
||||
sep_mv_len = 1;
|
||||
indent = 0;
|
||||
break;
|
||||
|
||||
case XN_FLAG_SEP_CPLUS_SPC:
|
||||
sep_dn = ", ";
|
||||
sep_dn_len = 2;
|
||||
sep_mv = " + ";
|
||||
sep_mv_len = 3;
|
||||
indent = 0;
|
||||
break;
|
||||
|
||||
case XN_FLAG_SEP_SPLUS_SPC:
|
||||
sep_dn = "; ";
|
||||
sep_dn_len = 2;
|
||||
sep_mv = " + ";
|
||||
sep_mv_len = 3;
|
||||
indent = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (flags & XN_FLAG_SPC_EQ) {
|
||||
sep_eq = " = ";
|
||||
sep_eq_len = 3;
|
||||
} else {
|
||||
sep_eq = "=";
|
||||
sep_eq_len = 1;
|
||||
}
|
||||
|
||||
fn_opt = flags & XN_FLAG_FN_MASK;
|
||||
|
||||
cnt = X509_NAME_entry_count(n);
|
||||
for (i = 0; i < cnt; i++) {
|
||||
if (flags & XN_FLAG_DN_REV)
|
||||
ent = X509_NAME_get_entry(n, cnt - i - 1);
|
||||
else
|
||||
ent = X509_NAME_get_entry(n, i);
|
||||
if (prev != -1) {
|
||||
if (prev == X509_NAME_ENTRY_set(ent)) {
|
||||
if (!io_ch(arg, sep_mv, sep_mv_len))
|
||||
return -1;
|
||||
outlen += sep_mv_len;
|
||||
} else {
|
||||
if (!io_ch(arg, sep_dn, sep_dn_len))
|
||||
return -1;
|
||||
outlen += sep_dn_len;
|
||||
if (!do_indent(io_ch, arg, indent))
|
||||
return -1;
|
||||
outlen += indent;
|
||||
}
|
||||
}
|
||||
prev = X509_NAME_ENTRY_set(ent);
|
||||
fn = X509_NAME_ENTRY_get_object(ent);
|
||||
val = X509_NAME_ENTRY_get_data(ent);
|
||||
fn_nid = OBJ_obj2nid(fn);
|
||||
if (fn_opt != XN_FLAG_FN_NONE) {
|
||||
int objlen, fld_len;
|
||||
if ((fn_opt == XN_FLAG_FN_OID) || (fn_nid == NID_undef)) {
|
||||
OBJ_obj2txt(objtmp, sizeof(objtmp), fn, 1);
|
||||
fld_len = 0; /* XXX: what should this be? */
|
||||
objbuf = objtmp;
|
||||
} else {
|
||||
if (fn_opt == XN_FLAG_FN_SN) {
|
||||
fld_len = FN_WIDTH_SN;
|
||||
objbuf = OBJ_nid2sn(fn_nid);
|
||||
} else if (fn_opt == XN_FLAG_FN_LN) {
|
||||
fld_len = FN_WIDTH_LN;
|
||||
objbuf = OBJ_nid2ln(fn_nid);
|
||||
} else {
|
||||
fld_len = 0; /* XXX: what should this be? */
|
||||
objbuf = "";
|
||||
}
|
||||
}
|
||||
objlen = strlen(objbuf);
|
||||
if (!io_ch(arg, objbuf, objlen))
|
||||
return -1;
|
||||
if ((objlen < fld_len) && (flags & XN_FLAG_FN_ALIGN)) {
|
||||
if (!do_indent(io_ch, arg, fld_len - objlen))
|
||||
return -1;
|
||||
outlen += fld_len - objlen;
|
||||
}
|
||||
if (!io_ch(arg, sep_eq, sep_eq_len))
|
||||
return -1;
|
||||
outlen += objlen + sep_eq_len;
|
||||
}
|
||||
/*
|
||||
* If the field name is unknown then fix up the DER dump flag. We
|
||||
* might want to limit this further so it will DER dump on anything
|
||||
* other than a few 'standard' fields.
|
||||
*/
|
||||
if ((fn_nid == NID_undef) && (flags & XN_FLAG_DUMP_UNKNOWN_FIELDS))
|
||||
orflags = ASN1_STRFLGS_DUMP_ALL;
|
||||
else
|
||||
orflags = 0;
|
||||
|
||||
len = do_print_ex(io_ch, arg, flags | orflags, val);
|
||||
if (len < 0)
|
||||
return -1;
|
||||
outlen += len;
|
||||
}
|
||||
return outlen;
|
||||
}
|
||||
|
||||
/* Wrappers round the main functions */
|
||||
|
||||
int X509_NAME_print_ex(BIO *out, const X509_NAME *nm, int indent,
|
||||
unsigned long flags)
|
||||
{
|
||||
if (flags == XN_FLAG_COMPAT)
|
||||
return X509_NAME_print(out, nm, indent);
|
||||
return do_name_ex(send_bio_chars, out, nm, indent, flags);
|
||||
}
|
||||
|
||||
#ifndef OPENSSL_NO_STDIO
|
||||
int X509_NAME_print_ex_fp(FILE *fp, const X509_NAME *nm, int indent,
|
||||
unsigned long flags)
|
||||
{
|
||||
if (flags == XN_FLAG_COMPAT) {
|
||||
BIO *btmp;
|
||||
int ret;
|
||||
btmp = BIO_new_fp(fp, BIO_NOCLOSE);
|
||||
if (!btmp)
|
||||
return -1;
|
||||
ret = X509_NAME_print(btmp, nm, indent);
|
||||
BIO_free(btmp);
|
||||
return ret;
|
||||
}
|
||||
return do_name_ex(send_fp_chars, fp, nm, indent, flags);
|
||||
}
|
||||
#endif
|
||||
|
||||
int ASN1_STRING_print_ex(BIO *out, const ASN1_STRING *str, unsigned long flags)
|
||||
{
|
||||
return do_print_ex(send_bio_chars, out, flags, str);
|
||||
}
|
||||
|
||||
#ifndef OPENSSL_NO_STDIO
|
||||
int ASN1_STRING_print_ex_fp(FILE *fp, const ASN1_STRING *str, unsigned long flags)
|
||||
{
|
||||
return do_print_ex(send_fp_chars, fp, flags, str);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Utility function: convert any string type to UTF8, returns number of bytes
|
||||
* in output string or a negative error code
|
||||
*/
|
||||
|
||||
int ASN1_STRING_to_UTF8(unsigned char **out, const ASN1_STRING *in)
|
||||
{
|
||||
ASN1_STRING stmp, *str = &stmp;
|
||||
int mbflag, type, ret;
|
||||
if (!in)
|
||||
return -1;
|
||||
type = in->type;
|
||||
if ((type < 0) || (type > 30))
|
||||
return -1;
|
||||
mbflag = tag2nbyte[type];
|
||||
if (mbflag == -1)
|
||||
return -1;
|
||||
mbflag |= MBSTRING_FLAG;
|
||||
stmp.data = NULL;
|
||||
stmp.length = 0;
|
||||
stmp.flags = 0;
|
||||
ret =
|
||||
ASN1_mbstring_copy(&str, in->data, in->length, mbflag,
|
||||
B_ASN1_UTF8STRING);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
*out = stmp.data;
|
||||
return stmp.length;
|
||||
}
|
||||
219
crypto/asn1/a_strnid.c
Normal file
219
crypto/asn1/a_strnid.c
Normal file
@@ -0,0 +1,219 @@
|
||||
/*
|
||||
* Copyright 1999-2018 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "internal/cryptlib.h"
|
||||
#include <openssl/asn1.h>
|
||||
#include <openssl/objects.h>
|
||||
|
||||
static STACK_OF(ASN1_STRING_TABLE) *stable = NULL;
|
||||
static void st_free(ASN1_STRING_TABLE *tbl);
|
||||
static int sk_table_cmp(const ASN1_STRING_TABLE *const *a,
|
||||
const ASN1_STRING_TABLE *const *b);
|
||||
|
||||
/*
|
||||
* This is the global mask for the mbstring functions: this is use to mask
|
||||
* out certain types (such as BMPString and UTF8String) because certain
|
||||
* software (e.g. Netscape) has problems with them.
|
||||
*/
|
||||
|
||||
static unsigned long global_mask = B_ASN1_UTF8STRING;
|
||||
|
||||
void ASN1_STRING_set_default_mask(unsigned long mask)
|
||||
{
|
||||
global_mask = mask;
|
||||
}
|
||||
|
||||
unsigned long ASN1_STRING_get_default_mask(void)
|
||||
{
|
||||
return global_mask;
|
||||
}
|
||||
|
||||
/*-
|
||||
* This function sets the default to various "flavours" of configuration.
|
||||
* based on an ASCII string. Currently this is:
|
||||
* MASK:XXXX : a numerical mask value.
|
||||
* nobmp : Don't use BMPStrings (just Printable, T61).
|
||||
* pkix : PKIX recommendation in RFC2459.
|
||||
* utf8only : only use UTF8Strings (RFC2459 recommendation for 2004).
|
||||
* default: the default value, Printable, T61, BMP.
|
||||
*/
|
||||
|
||||
int ASN1_STRING_set_default_mask_asc(const char *p)
|
||||
{
|
||||
unsigned long mask;
|
||||
char *end;
|
||||
|
||||
if (strncmp(p, "MASK:", 5) == 0) {
|
||||
if (!p[5])
|
||||
return 0;
|
||||
mask = strtoul(p + 5, &end, 0);
|
||||
if (*end)
|
||||
return 0;
|
||||
} else if (strcmp(p, "nombstr") == 0)
|
||||
mask = ~((unsigned long)(B_ASN1_BMPSTRING | B_ASN1_UTF8STRING));
|
||||
else if (strcmp(p, "pkix") == 0)
|
||||
mask = ~((unsigned long)B_ASN1_T61STRING);
|
||||
else if (strcmp(p, "utf8only") == 0)
|
||||
mask = B_ASN1_UTF8STRING;
|
||||
else if (strcmp(p, "default") == 0)
|
||||
mask = 0xFFFFFFFFL;
|
||||
else
|
||||
return 0;
|
||||
ASN1_STRING_set_default_mask(mask);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* The following function generates an ASN1_STRING based on limits in a
|
||||
* table. Frequently the types and length of an ASN1_STRING are restricted by
|
||||
* a corresponding OID. For example certificates and certificate requests.
|
||||
*/
|
||||
|
||||
ASN1_STRING *ASN1_STRING_set_by_NID(ASN1_STRING **out,
|
||||
const unsigned char *in, int inlen,
|
||||
int inform, int nid)
|
||||
{
|
||||
ASN1_STRING_TABLE *tbl;
|
||||
ASN1_STRING *str = NULL;
|
||||
unsigned long mask;
|
||||
int ret;
|
||||
|
||||
if (out == NULL)
|
||||
out = &str;
|
||||
tbl = ASN1_STRING_TABLE_get(nid);
|
||||
if (tbl != NULL) {
|
||||
mask = tbl->mask;
|
||||
if (!(tbl->flags & STABLE_NO_MASK))
|
||||
mask &= global_mask;
|
||||
ret = ASN1_mbstring_ncopy(out, in, inlen, inform, mask,
|
||||
tbl->minsize, tbl->maxsize);
|
||||
} else {
|
||||
ret = ASN1_mbstring_copy(out, in, inlen, inform,
|
||||
DIRSTRING_TYPE & global_mask);
|
||||
}
|
||||
if (ret <= 0)
|
||||
return NULL;
|
||||
return *out;
|
||||
}
|
||||
|
||||
/*
|
||||
* Now the tables and helper functions for the string table:
|
||||
*/
|
||||
|
||||
#include "tbl_standard.h"
|
||||
|
||||
static int sk_table_cmp(const ASN1_STRING_TABLE *const *a,
|
||||
const ASN1_STRING_TABLE *const *b)
|
||||
{
|
||||
return (*a)->nid - (*b)->nid;
|
||||
}
|
||||
|
||||
DECLARE_OBJ_BSEARCH_CMP_FN(ASN1_STRING_TABLE, ASN1_STRING_TABLE, table);
|
||||
|
||||
static int table_cmp(const ASN1_STRING_TABLE *a, const ASN1_STRING_TABLE *b)
|
||||
{
|
||||
return a->nid - b->nid;
|
||||
}
|
||||
|
||||
IMPLEMENT_OBJ_BSEARCH_CMP_FN(ASN1_STRING_TABLE, ASN1_STRING_TABLE, table);
|
||||
|
||||
ASN1_STRING_TABLE *ASN1_STRING_TABLE_get(int nid)
|
||||
{
|
||||
int idx;
|
||||
ASN1_STRING_TABLE fnd;
|
||||
|
||||
fnd.nid = nid;
|
||||
if (stable) {
|
||||
idx = sk_ASN1_STRING_TABLE_find(stable, &fnd);
|
||||
if (idx >= 0)
|
||||
return sk_ASN1_STRING_TABLE_value(stable, idx);
|
||||
}
|
||||
return OBJ_bsearch_table(&fnd, tbl_standard, OSSL_NELEM(tbl_standard));
|
||||
}
|
||||
|
||||
/*
|
||||
* Return a string table pointer which can be modified: either directly from
|
||||
* table or a copy of an internal value added to the table.
|
||||
*/
|
||||
|
||||
static ASN1_STRING_TABLE *stable_get(int nid)
|
||||
{
|
||||
ASN1_STRING_TABLE *tmp, *rv;
|
||||
|
||||
/* Always need a string table so allocate one if NULL */
|
||||
if (stable == NULL) {
|
||||
stable = sk_ASN1_STRING_TABLE_new(sk_table_cmp);
|
||||
if (stable == NULL)
|
||||
return NULL;
|
||||
}
|
||||
tmp = ASN1_STRING_TABLE_get(nid);
|
||||
if (tmp != NULL && tmp->flags & STABLE_FLAGS_MALLOC)
|
||||
return tmp;
|
||||
if ((rv = OPENSSL_zalloc(sizeof(*rv))) == NULL) {
|
||||
ASN1err(ASN1_F_STABLE_GET, ERR_R_MALLOC_FAILURE);
|
||||
return NULL;
|
||||
}
|
||||
if (!sk_ASN1_STRING_TABLE_push(stable, rv)) {
|
||||
OPENSSL_free(rv);
|
||||
return NULL;
|
||||
}
|
||||
if (tmp != NULL) {
|
||||
rv->nid = tmp->nid;
|
||||
rv->minsize = tmp->minsize;
|
||||
rv->maxsize = tmp->maxsize;
|
||||
rv->mask = tmp->mask;
|
||||
rv->flags = tmp->flags | STABLE_FLAGS_MALLOC;
|
||||
} else {
|
||||
rv->nid = nid;
|
||||
rv->minsize = -1;
|
||||
rv->maxsize = -1;
|
||||
rv->flags = STABLE_FLAGS_MALLOC;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
int ASN1_STRING_TABLE_add(int nid,
|
||||
long minsize, long maxsize, unsigned long mask,
|
||||
unsigned long flags)
|
||||
{
|
||||
ASN1_STRING_TABLE *tmp;
|
||||
|
||||
tmp = stable_get(nid);
|
||||
if (tmp == NULL) {
|
||||
ASN1err(ASN1_F_ASN1_STRING_TABLE_ADD, ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
if (minsize >= 0)
|
||||
tmp->minsize = minsize;
|
||||
if (maxsize >= 0)
|
||||
tmp->maxsize = maxsize;
|
||||
if (mask)
|
||||
tmp->mask = mask;
|
||||
if (flags)
|
||||
tmp->flags = STABLE_FLAGS_MALLOC | flags;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void ASN1_STRING_TABLE_cleanup(void)
|
||||
{
|
||||
STACK_OF(ASN1_STRING_TABLE) *tmp;
|
||||
|
||||
tmp = stable;
|
||||
if (tmp == NULL)
|
||||
return;
|
||||
stable = NULL;
|
||||
sk_ASN1_STRING_TABLE_pop_free(tmp, st_free);
|
||||
}
|
||||
|
||||
static void st_free(ASN1_STRING_TABLE *tbl)
|
||||
{
|
||||
if (tbl->flags & STABLE_FLAGS_MALLOC)
|
||||
OPENSSL_free(tbl);
|
||||
}
|
||||
553
crypto/asn1/a_time.c
Normal file
553
crypto/asn1/a_time.c
Normal file
@@ -0,0 +1,553 @@
|
||||
/*
|
||||
* Copyright 1999-2017 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
/*-
|
||||
* This is an implementation of the ASN1 Time structure which is:
|
||||
* Time ::= CHOICE {
|
||||
* utcTime UTCTime,
|
||||
* generalTime GeneralizedTime }
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
#include "internal/ctype.h"
|
||||
#include "internal/cryptlib.h"
|
||||
#include <openssl/asn1t.h>
|
||||
#include "asn1_locl.h"
|
||||
|
||||
IMPLEMENT_ASN1_MSTRING(ASN1_TIME, B_ASN1_TIME)
|
||||
|
||||
IMPLEMENT_ASN1_FUNCTIONS(ASN1_TIME)
|
||||
|
||||
static int is_utc(const int year)
|
||||
{
|
||||
if (50 <= year && year <= 149)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int leap_year(const int year)
|
||||
{
|
||||
if (year % 400 == 0 || (year % 100 != 0 && year % 4 == 0))
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Compute the day of the week and the day of the year from the year, month
|
||||
* and day. The day of the year is straightforward, the day of the week uses
|
||||
* a form of Zeller's congruence. For this months start with March and are
|
||||
* numbered 4 through 15.
|
||||
*/
|
||||
static void determine_days(struct tm *tm)
|
||||
{
|
||||
static const int ydays[12] = {
|
||||
0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334
|
||||
};
|
||||
int y = tm->tm_year + 1900;
|
||||
int m = tm->tm_mon;
|
||||
int d = tm->tm_mday;
|
||||
int c;
|
||||
|
||||
tm->tm_yday = ydays[m] + d - 1;
|
||||
if (m >= 2) {
|
||||
/* March and onwards can be one day further into the year */
|
||||
tm->tm_yday += leap_year(y);
|
||||
m += 2;
|
||||
} else {
|
||||
/* Treat January and February as part of the previous year */
|
||||
m += 14;
|
||||
y--;
|
||||
}
|
||||
c = y / 100;
|
||||
y %= 100;
|
||||
/* Zeller's congruance */
|
||||
tm->tm_wday = (d + (13 * m) / 5 + y + y / 4 + c / 4 + 5 * c + 6) % 7;
|
||||
}
|
||||
|
||||
int asn1_time_to_tm(struct tm *tm, const ASN1_TIME *d)
|
||||
{
|
||||
static const int min[9] = { 0, 0, 1, 1, 0, 0, 0, 0, 0 };
|
||||
static const int max[9] = { 99, 99, 12, 31, 23, 59, 59, 12, 59 };
|
||||
static const int mdays[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
|
||||
char *a;
|
||||
int n, i, i2, l, o, min_l = 11, strict = 0, end = 6, btz = 5, md;
|
||||
struct tm tmp;
|
||||
|
||||
/*
|
||||
* ASN1_STRING_FLAG_X509_TIME is used to enforce RFC 5280
|
||||
* time string format, in which:
|
||||
*
|
||||
* 1. "seconds" is a 'MUST'
|
||||
* 2. "Zulu" timezone is a 'MUST'
|
||||
* 3. "+|-" is not allowed to indicate a time zone
|
||||
*/
|
||||
if (d->type == V_ASN1_UTCTIME) {
|
||||
if (d->flags & ASN1_STRING_FLAG_X509_TIME) {
|
||||
min_l = 13;
|
||||
strict = 1;
|
||||
}
|
||||
} else if (d->type == V_ASN1_GENERALIZEDTIME) {
|
||||
end = 7;
|
||||
btz = 6;
|
||||
if (d->flags & ASN1_STRING_FLAG_X509_TIME) {
|
||||
min_l = 15;
|
||||
strict = 1;
|
||||
} else {
|
||||
min_l = 13;
|
||||
}
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
|
||||
l = d->length;
|
||||
a = (char *)d->data;
|
||||
o = 0;
|
||||
memset(&tmp, 0, sizeof(tmp));
|
||||
|
||||
/*
|
||||
* GENERALIZEDTIME is similar to UTCTIME except the year is represented
|
||||
* as YYYY. This stuff treats everything as a two digit field so make
|
||||
* first two fields 00 to 99
|
||||
*/
|
||||
|
||||
if (l < min_l)
|
||||
goto err;
|
||||
for (i = 0; i < end; i++) {
|
||||
if (!strict && (i == btz) && ((a[o] == 'Z') || (a[o] == '+') || (a[o] == '-'))) {
|
||||
i++;
|
||||
break;
|
||||
}
|
||||
if (!ossl_isdigit(a[o]))
|
||||
goto err;
|
||||
n = a[o] - '0';
|
||||
/* incomplete 2-digital number */
|
||||
if (++o == l)
|
||||
goto err;
|
||||
|
||||
if (!ossl_isdigit(a[o]))
|
||||
goto err;
|
||||
n = (n * 10) + a[o] - '0';
|
||||
/* no more bytes to read, but we haven't seen time-zone yet */
|
||||
if (++o == l)
|
||||
goto err;
|
||||
|
||||
i2 = (d->type == V_ASN1_UTCTIME) ? i + 1 : i;
|
||||
|
||||
if ((n < min[i2]) || (n > max[i2]))
|
||||
goto err;
|
||||
switch (i2) {
|
||||
case 0:
|
||||
/* UTC will never be here */
|
||||
tmp.tm_year = n * 100 - 1900;
|
||||
break;
|
||||
case 1:
|
||||
if (d->type == V_ASN1_UTCTIME)
|
||||
tmp.tm_year = n < 50 ? n + 100 : n;
|
||||
else
|
||||
tmp.tm_year += n;
|
||||
break;
|
||||
case 2:
|
||||
tmp.tm_mon = n - 1;
|
||||
break;
|
||||
case 3:
|
||||
/* check if tm_mday is valid in tm_mon */
|
||||
if (tmp.tm_mon == 1) {
|
||||
/* it's February */
|
||||
md = mdays[1] + leap_year(tmp.tm_year + 1900);
|
||||
} else {
|
||||
md = mdays[tmp.tm_mon];
|
||||
}
|
||||
if (n > md)
|
||||
goto err;
|
||||
tmp.tm_mday = n;
|
||||
determine_days(&tmp);
|
||||
break;
|
||||
case 4:
|
||||
tmp.tm_hour = n;
|
||||
break;
|
||||
case 5:
|
||||
tmp.tm_min = n;
|
||||
break;
|
||||
case 6:
|
||||
tmp.tm_sec = n;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Optional fractional seconds: decimal point followed by one or more
|
||||
* digits.
|
||||
*/
|
||||
if (d->type == V_ASN1_GENERALIZEDTIME && a[o] == '.') {
|
||||
if (strict)
|
||||
/* RFC 5280 forbids fractional seconds */
|
||||
goto err;
|
||||
if (++o == l)
|
||||
goto err;
|
||||
i = o;
|
||||
while ((o < l) && ossl_isdigit(a[o]))
|
||||
o++;
|
||||
/* Must have at least one digit after decimal point */
|
||||
if (i == o)
|
||||
goto err;
|
||||
/* no more bytes to read, but we haven't seen time-zone yet */
|
||||
if (o == l)
|
||||
goto err;
|
||||
}
|
||||
|
||||
/*
|
||||
* 'o' will never point to '\0' at this point, the only chance
|
||||
* 'o' can point to '\0' is either the subsequent if or the first
|
||||
* else if is true.
|
||||
*/
|
||||
if (a[o] == 'Z') {
|
||||
o++;
|
||||
} else if (!strict && ((a[o] == '+') || (a[o] == '-'))) {
|
||||
int offsign = a[o] == '-' ? 1 : -1;
|
||||
int offset = 0;
|
||||
|
||||
o++;
|
||||
/*
|
||||
* if not equal, no need to do subsequent checks
|
||||
* since the following for-loop will add 'o' by 4
|
||||
* and the final return statement will check if 'l'
|
||||
* and 'o' are equal.
|
||||
*/
|
||||
if (o + 4 != l)
|
||||
goto err;
|
||||
for (i = end; i < end + 2; i++) {
|
||||
if (!ossl_isdigit(a[o]))
|
||||
goto err;
|
||||
n = a[o] - '0';
|
||||
o++;
|
||||
if (!ossl_isdigit(a[o]))
|
||||
goto err;
|
||||
n = (n * 10) + a[o] - '0';
|
||||
i2 = (d->type == V_ASN1_UTCTIME) ? i + 1 : i;
|
||||
if ((n < min[i2]) || (n > max[i2]))
|
||||
goto err;
|
||||
/* if tm is NULL, no need to adjust */
|
||||
if (tm != NULL) {
|
||||
if (i == end)
|
||||
offset = n * 3600;
|
||||
else if (i == end + 1)
|
||||
offset += n * 60;
|
||||
}
|
||||
o++;
|
||||
}
|
||||
if (offset && !OPENSSL_gmtime_adj(&tmp, 0, offset * offsign))
|
||||
goto err;
|
||||
} else {
|
||||
/* not Z, or not +/- in non-strict mode */
|
||||
goto err;
|
||||
}
|
||||
if (o == l) {
|
||||
/* success, check if tm should be filled */
|
||||
if (tm != NULL)
|
||||
*tm = tmp;
|
||||
return 1;
|
||||
}
|
||||
err:
|
||||
return 0;
|
||||
}
|
||||
|
||||
ASN1_TIME *asn1_time_from_tm(ASN1_TIME *s, struct tm *ts, int type)
|
||||
{
|
||||
char* p;
|
||||
ASN1_TIME *tmps = NULL;
|
||||
const size_t len = 20;
|
||||
|
||||
if (type == V_ASN1_UNDEF) {
|
||||
if (is_utc(ts->tm_year))
|
||||
type = V_ASN1_UTCTIME;
|
||||
else
|
||||
type = V_ASN1_GENERALIZEDTIME;
|
||||
} else if (type == V_ASN1_UTCTIME) {
|
||||
if (!is_utc(ts->tm_year))
|
||||
goto err;
|
||||
} else if (type != V_ASN1_GENERALIZEDTIME) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (s == NULL)
|
||||
tmps = ASN1_STRING_new();
|
||||
else
|
||||
tmps = s;
|
||||
if (tmps == NULL)
|
||||
return NULL;
|
||||
|
||||
if (!ASN1_STRING_set(tmps, NULL, len))
|
||||
goto err;
|
||||
|
||||
tmps->type = type;
|
||||
p = (char*)tmps->data;
|
||||
|
||||
if (type == V_ASN1_GENERALIZEDTIME)
|
||||
tmps->length = BIO_snprintf(p, len, "%04d%02d%02d%02d%02d%02dZ",
|
||||
ts->tm_year + 1900, ts->tm_mon + 1,
|
||||
ts->tm_mday, ts->tm_hour, ts->tm_min,
|
||||
ts->tm_sec);
|
||||
else
|
||||
tmps->length = BIO_snprintf(p, len, "%02d%02d%02d%02d%02d%02dZ",
|
||||
ts->tm_year % 100, ts->tm_mon + 1,
|
||||
ts->tm_mday, ts->tm_hour, ts->tm_min,
|
||||
ts->tm_sec);
|
||||
|
||||
#ifdef CHARSET_EBCDIC_not
|
||||
ebcdic2ascii(tmps->data, tmps->data, tmps->length);
|
||||
#endif
|
||||
return tmps;
|
||||
err:
|
||||
if (tmps != s)
|
||||
ASN1_STRING_free(tmps);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ASN1_TIME *ASN1_TIME_set(ASN1_TIME *s, time_t t)
|
||||
{
|
||||
return ASN1_TIME_adj(s, t, 0, 0);
|
||||
}
|
||||
|
||||
ASN1_TIME *ASN1_TIME_adj(ASN1_TIME *s, time_t t,
|
||||
int offset_day, long offset_sec)
|
||||
{
|
||||
struct tm *ts;
|
||||
struct tm data;
|
||||
|
||||
ts = OPENSSL_gmtime(&t, &data);
|
||||
if (ts == NULL) {
|
||||
ASN1err(ASN1_F_ASN1_TIME_ADJ, ASN1_R_ERROR_GETTING_TIME);
|
||||
return NULL;
|
||||
}
|
||||
if (offset_day || offset_sec) {
|
||||
if (!OPENSSL_gmtime_adj(ts, offset_day, offset_sec))
|
||||
return NULL;
|
||||
}
|
||||
return asn1_time_from_tm(s, ts, V_ASN1_UNDEF);
|
||||
}
|
||||
|
||||
int ASN1_TIME_check(const ASN1_TIME *t)
|
||||
{
|
||||
if (t->type == V_ASN1_GENERALIZEDTIME)
|
||||
return ASN1_GENERALIZEDTIME_check(t);
|
||||
else if (t->type == V_ASN1_UTCTIME)
|
||||
return ASN1_UTCTIME_check(t);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Convert an ASN1_TIME structure to GeneralizedTime */
|
||||
ASN1_GENERALIZEDTIME *ASN1_TIME_to_generalizedtime(const ASN1_TIME *t,
|
||||
ASN1_GENERALIZEDTIME **out)
|
||||
{
|
||||
ASN1_GENERALIZEDTIME *ret = NULL;
|
||||
struct tm tm;
|
||||
|
||||
if (!ASN1_TIME_to_tm(t, &tm))
|
||||
return NULL;
|
||||
|
||||
if (out != NULL)
|
||||
ret = *out;
|
||||
|
||||
ret = asn1_time_from_tm(ret, &tm, V_ASN1_GENERALIZEDTIME);
|
||||
|
||||
if (out != NULL && ret != NULL)
|
||||
*out = ret;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ASN1_TIME_set_string(ASN1_TIME *s, const char *str)
|
||||
{
|
||||
/* Try UTC, if that fails, try GENERALIZED */
|
||||
if (ASN1_UTCTIME_set_string(s, str))
|
||||
return 1;
|
||||
return ASN1_GENERALIZEDTIME_set_string(s, str);
|
||||
}
|
||||
|
||||
int ASN1_TIME_set_string_X509(ASN1_TIME *s, const char *str)
|
||||
{
|
||||
ASN1_TIME t;
|
||||
struct tm tm;
|
||||
int rv = 0;
|
||||
|
||||
t.length = strlen(str);
|
||||
t.data = (unsigned char *)str;
|
||||
t.flags = ASN1_STRING_FLAG_X509_TIME;
|
||||
|
||||
t.type = V_ASN1_UTCTIME;
|
||||
|
||||
if (!ASN1_TIME_check(&t)) {
|
||||
t.type = V_ASN1_GENERALIZEDTIME;
|
||||
if (!ASN1_TIME_check(&t))
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* Per RFC 5280 (section 4.1.2.5.), the valid input time
|
||||
* strings should be encoded with the following rules:
|
||||
*
|
||||
* 1. UTC: YYMMDDHHMMSSZ, if YY < 50 (20YY) --> UTC: YYMMDDHHMMSSZ
|
||||
* 2. UTC: YYMMDDHHMMSSZ, if YY >= 50 (19YY) --> UTC: YYMMDDHHMMSSZ
|
||||
* 3. G'd: YYYYMMDDHHMMSSZ, if YYYY >= 2050 --> G'd: YYYYMMDDHHMMSSZ
|
||||
* 4. G'd: YYYYMMDDHHMMSSZ, if YYYY < 2050 --> UTC: YYMMDDHHMMSSZ
|
||||
*
|
||||
* Only strings of the 4th rule should be reformatted, but since a
|
||||
* UTC can only present [1950, 2050), so if the given time string
|
||||
* is less than 1950 (e.g. 19230419000000Z), we do nothing...
|
||||
*/
|
||||
|
||||
if (s != NULL && t.type == V_ASN1_GENERALIZEDTIME) {
|
||||
if (!asn1_time_to_tm(&tm, &t))
|
||||
goto out;
|
||||
if (is_utc(tm.tm_year)) {
|
||||
t.length -= 2;
|
||||
/*
|
||||
* it's OK to let original t.data go since that's assigned
|
||||
* to a piece of memory allocated outside of this function.
|
||||
* new t.data would be freed after ASN1_STRING_copy is done.
|
||||
*/
|
||||
t.data = OPENSSL_zalloc(t.length + 1);
|
||||
if (t.data == NULL)
|
||||
goto out;
|
||||
memcpy(t.data, str + 2, t.length);
|
||||
t.type = V_ASN1_UTCTIME;
|
||||
}
|
||||
}
|
||||
|
||||
if (s == NULL || ASN1_STRING_copy((ASN1_STRING *)s, (ASN1_STRING *)&t))
|
||||
rv = 1;
|
||||
|
||||
if (t.data != (unsigned char *)str)
|
||||
OPENSSL_free(t.data);
|
||||
out:
|
||||
return rv;
|
||||
}
|
||||
|
||||
int ASN1_TIME_to_tm(const ASN1_TIME *s, struct tm *tm)
|
||||
{
|
||||
if (s == NULL) {
|
||||
time_t now_t;
|
||||
|
||||
time(&now_t);
|
||||
memset(tm, 0, sizeof(*tm));
|
||||
if (OPENSSL_gmtime(&now_t, tm) != NULL)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return asn1_time_to_tm(tm, s);
|
||||
}
|
||||
|
||||
int ASN1_TIME_diff(int *pday, int *psec,
|
||||
const ASN1_TIME *from, const ASN1_TIME *to)
|
||||
{
|
||||
struct tm tm_from, tm_to;
|
||||
|
||||
if (!ASN1_TIME_to_tm(from, &tm_from))
|
||||
return 0;
|
||||
if (!ASN1_TIME_to_tm(to, &tm_to))
|
||||
return 0;
|
||||
return OPENSSL_gmtime_diff(pday, psec, &tm_from, &tm_to);
|
||||
}
|
||||
|
||||
static const char _asn1_mon[12][4] = {
|
||||
"Jan", "Feb", "Mar", "Apr", "May", "Jun",
|
||||
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
|
||||
};
|
||||
|
||||
int ASN1_TIME_print(BIO *bp, const ASN1_TIME *tm)
|
||||
{
|
||||
char *v;
|
||||
int gmt = 0, l;
|
||||
struct tm stm;
|
||||
|
||||
if (!asn1_time_to_tm(&stm, tm)) {
|
||||
/* asn1_time_to_tm will check the time type */
|
||||
goto err;
|
||||
}
|
||||
|
||||
l = tm->length;
|
||||
v = (char *)tm->data;
|
||||
if (v[l - 1] == 'Z')
|
||||
gmt = 1;
|
||||
|
||||
if (tm->type == V_ASN1_GENERALIZEDTIME) {
|
||||
char *f = NULL;
|
||||
int f_len = 0;
|
||||
|
||||
/*
|
||||
* Try to parse fractional seconds. '14' is the place of
|
||||
* 'fraction point' in a GeneralizedTime string.
|
||||
*/
|
||||
if (tm->length > 15 && v[14] == '.') {
|
||||
f = &v[14];
|
||||
f_len = 1;
|
||||
while (14 + f_len < l && ossl_isdigit(f[f_len]))
|
||||
++f_len;
|
||||
}
|
||||
|
||||
return BIO_printf(bp, "%s %2d %02d:%02d:%02d%.*s %d%s",
|
||||
_asn1_mon[stm.tm_mon], stm.tm_mday, stm.tm_hour,
|
||||
stm.tm_min, stm.tm_sec, f_len, f, stm.tm_year + 1900,
|
||||
(gmt ? " GMT" : "")) > 0;
|
||||
} else {
|
||||
return BIO_printf(bp, "%s %2d %02d:%02d:%02d %d%s",
|
||||
_asn1_mon[stm.tm_mon], stm.tm_mday, stm.tm_hour,
|
||||
stm.tm_min, stm.tm_sec, stm.tm_year + 1900,
|
||||
(gmt ? " GMT" : "")) > 0;
|
||||
}
|
||||
err:
|
||||
BIO_write(bp, "Bad time value", 14);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ASN1_TIME_cmp_time_t(const ASN1_TIME *s, time_t t)
|
||||
{
|
||||
struct tm stm, ttm;
|
||||
int day, sec;
|
||||
|
||||
if (!ASN1_TIME_to_tm(s, &stm))
|
||||
return -2;
|
||||
|
||||
if (!OPENSSL_gmtime(&t, &ttm))
|
||||
return -2;
|
||||
|
||||
if (!OPENSSL_gmtime_diff(&day, &sec, &ttm, &stm))
|
||||
return -2;
|
||||
|
||||
if (day > 0 || sec > 0)
|
||||
return 1;
|
||||
if (day < 0 || sec < 0)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ASN1_TIME_normalize(ASN1_TIME *t)
|
||||
{
|
||||
struct tm tm;
|
||||
|
||||
if (!ASN1_TIME_to_tm(t, &tm))
|
||||
return 0;
|
||||
|
||||
return asn1_time_from_tm(t, &tm, V_ASN1_UNDEF) != NULL;
|
||||
}
|
||||
|
||||
int ASN1_TIME_compare(const ASN1_TIME *a, const ASN1_TIME *b)
|
||||
{
|
||||
int day, sec;
|
||||
|
||||
if (!ASN1_TIME_diff(&day, &sec, b, a))
|
||||
return -2;
|
||||
if (day > 0 || sec > 0)
|
||||
return 1;
|
||||
if (day < 0 || sec < 0)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
134
crypto/asn1/a_type.c
Normal file
134
crypto/asn1/a_type.c
Normal file
@@ -0,0 +1,134 @@
|
||||
/*
|
||||
* Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "internal/cryptlib.h"
|
||||
#include <openssl/asn1t.h>
|
||||
#include <openssl/objects.h>
|
||||
#include "asn1_locl.h"
|
||||
|
||||
int ASN1_TYPE_get(const ASN1_TYPE *a)
|
||||
{
|
||||
if ((a->value.ptr != NULL) || (a->type == V_ASN1_NULL))
|
||||
return a->type;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ASN1_TYPE_set(ASN1_TYPE *a, int type, void *value)
|
||||
{
|
||||
if (a->value.ptr != NULL) {
|
||||
ASN1_TYPE **tmp_a = &a;
|
||||
asn1_primitive_free((ASN1_VALUE **)tmp_a, NULL, 0);
|
||||
}
|
||||
a->type = type;
|
||||
if (type == V_ASN1_BOOLEAN)
|
||||
a->value.boolean = value ? 0xff : 0;
|
||||
else
|
||||
a->value.ptr = value;
|
||||
}
|
||||
|
||||
int ASN1_TYPE_set1(ASN1_TYPE *a, int type, const void *value)
|
||||
{
|
||||
if (!value || (type == V_ASN1_BOOLEAN)) {
|
||||
void *p = (void *)value;
|
||||
ASN1_TYPE_set(a, type, p);
|
||||
} else if (type == V_ASN1_OBJECT) {
|
||||
ASN1_OBJECT *odup;
|
||||
odup = OBJ_dup(value);
|
||||
if (!odup)
|
||||
return 0;
|
||||
ASN1_TYPE_set(a, type, odup);
|
||||
} else {
|
||||
ASN1_STRING *sdup;
|
||||
sdup = ASN1_STRING_dup(value);
|
||||
if (!sdup)
|
||||
return 0;
|
||||
ASN1_TYPE_set(a, type, sdup);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Returns 0 if they are equal, != 0 otherwise. */
|
||||
int ASN1_TYPE_cmp(const ASN1_TYPE *a, const ASN1_TYPE *b)
|
||||
{
|
||||
int result = -1;
|
||||
|
||||
if (!a || !b || a->type != b->type)
|
||||
return -1;
|
||||
|
||||
switch (a->type) {
|
||||
case V_ASN1_OBJECT:
|
||||
result = OBJ_cmp(a->value.object, b->value.object);
|
||||
break;
|
||||
case V_ASN1_BOOLEAN:
|
||||
result = a->value.boolean - b->value.boolean;
|
||||
break;
|
||||
case V_ASN1_NULL:
|
||||
result = 0; /* They do not have content. */
|
||||
break;
|
||||
case V_ASN1_INTEGER:
|
||||
case V_ASN1_ENUMERATED:
|
||||
case V_ASN1_BIT_STRING:
|
||||
case V_ASN1_OCTET_STRING:
|
||||
case V_ASN1_SEQUENCE:
|
||||
case V_ASN1_SET:
|
||||
case V_ASN1_NUMERICSTRING:
|
||||
case V_ASN1_PRINTABLESTRING:
|
||||
case V_ASN1_T61STRING:
|
||||
case V_ASN1_VIDEOTEXSTRING:
|
||||
case V_ASN1_IA5STRING:
|
||||
case V_ASN1_UTCTIME:
|
||||
case V_ASN1_GENERALIZEDTIME:
|
||||
case V_ASN1_GRAPHICSTRING:
|
||||
case V_ASN1_VISIBLESTRING:
|
||||
case V_ASN1_GENERALSTRING:
|
||||
case V_ASN1_UNIVERSALSTRING:
|
||||
case V_ASN1_BMPSTRING:
|
||||
case V_ASN1_UTF8STRING:
|
||||
case V_ASN1_OTHER:
|
||||
default:
|
||||
result = ASN1_STRING_cmp((ASN1_STRING *)a->value.ptr,
|
||||
(ASN1_STRING *)b->value.ptr);
|
||||
break;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
ASN1_TYPE *ASN1_TYPE_pack_sequence(const ASN1_ITEM *it, void *s, ASN1_TYPE **t)
|
||||
{
|
||||
ASN1_OCTET_STRING *oct;
|
||||
ASN1_TYPE *rt;
|
||||
|
||||
oct = ASN1_item_pack(s, it, NULL);
|
||||
if (oct == NULL)
|
||||
return NULL;
|
||||
|
||||
if (t && *t) {
|
||||
rt = *t;
|
||||
} else {
|
||||
rt = ASN1_TYPE_new();
|
||||
if (rt == NULL) {
|
||||
ASN1_OCTET_STRING_free(oct);
|
||||
return NULL;
|
||||
}
|
||||
if (t)
|
||||
*t = rt;
|
||||
}
|
||||
ASN1_TYPE_set(rt, V_ASN1_SEQUENCE, oct);
|
||||
return rt;
|
||||
}
|
||||
|
||||
void *ASN1_TYPE_unpack_sequence(const ASN1_ITEM *it, const ASN1_TYPE *t)
|
||||
{
|
||||
if (t == NULL || t->type != V_ASN1_SEQUENCE || t->value.sequence == NULL)
|
||||
return NULL;
|
||||
return ASN1_item_unpack(t->value.sequence, it);
|
||||
}
|
||||
98
crypto/asn1/a_utctm.c
Normal file
98
crypto/asn1/a_utctm.c
Normal file
@@ -0,0 +1,98 @@
|
||||
/*
|
||||
* Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
#include "internal/cryptlib.h"
|
||||
#include <openssl/asn1.h>
|
||||
#include "asn1_locl.h"
|
||||
|
||||
/* This is the primary function used to parse ASN1_UTCTIME */
|
||||
int asn1_utctime_to_tm(struct tm *tm, const ASN1_UTCTIME *d)
|
||||
{
|
||||
/* wrapper around ans1_time_to_tm */
|
||||
if (d->type != V_ASN1_UTCTIME)
|
||||
return 0;
|
||||
return asn1_time_to_tm(tm, d);
|
||||
}
|
||||
|
||||
int ASN1_UTCTIME_check(const ASN1_UTCTIME *d)
|
||||
{
|
||||
return asn1_utctime_to_tm(NULL, d);
|
||||
}
|
||||
|
||||
/* Sets the string via simple copy without cleaning it up */
|
||||
int ASN1_UTCTIME_set_string(ASN1_UTCTIME *s, const char *str)
|
||||
{
|
||||
ASN1_UTCTIME t;
|
||||
|
||||
t.type = V_ASN1_UTCTIME;
|
||||
t.length = strlen(str);
|
||||
t.data = (unsigned char *)str;
|
||||
t.flags = 0;
|
||||
|
||||
if (!ASN1_UTCTIME_check(&t))
|
||||
return 0;
|
||||
|
||||
if (s != NULL && !ASN1_STRING_copy(s, &t))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
ASN1_UTCTIME *ASN1_UTCTIME_set(ASN1_UTCTIME *s, time_t t)
|
||||
{
|
||||
return ASN1_UTCTIME_adj(s, t, 0, 0);
|
||||
}
|
||||
|
||||
ASN1_UTCTIME *ASN1_UTCTIME_adj(ASN1_UTCTIME *s, time_t t,
|
||||
int offset_day, long offset_sec)
|
||||
{
|
||||
struct tm *ts;
|
||||
struct tm data;
|
||||
|
||||
ts = OPENSSL_gmtime(&t, &data);
|
||||
if (ts == NULL)
|
||||
return NULL;
|
||||
|
||||
if (offset_day || offset_sec) {
|
||||
if (!OPENSSL_gmtime_adj(ts, offset_day, offset_sec))
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return asn1_time_from_tm(s, ts, V_ASN1_UTCTIME);
|
||||
}
|
||||
|
||||
int ASN1_UTCTIME_cmp_time_t(const ASN1_UTCTIME *s, time_t t)
|
||||
{
|
||||
struct tm stm, ttm;
|
||||
int day, sec;
|
||||
|
||||
if (!asn1_utctime_to_tm(&stm, s))
|
||||
return -2;
|
||||
|
||||
if (OPENSSL_gmtime(&t, &ttm) == NULL)
|
||||
return -2;
|
||||
|
||||
if (!OPENSSL_gmtime_diff(&day, &sec, &ttm, &stm))
|
||||
return -2;
|
||||
|
||||
if (day > 0 || sec > 0)
|
||||
return 1;
|
||||
if (day < 0 || sec < 0)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ASN1_UTCTIME_print(BIO *bp, const ASN1_UTCTIME *tm)
|
||||
{
|
||||
if (tm->type != V_ASN1_UTCTIME)
|
||||
return 0;
|
||||
return ASN1_TIME_print(bp, tm);
|
||||
}
|
||||
188
crypto/asn1/a_utf8.c
Normal file
188
crypto/asn1/a_utf8.c
Normal file
@@ -0,0 +1,188 @@
|
||||
/*
|
||||
* Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "internal/cryptlib.h"
|
||||
#include <openssl/asn1.h>
|
||||
|
||||
/* UTF8 utilities */
|
||||
|
||||
/*-
|
||||
* This parses a UTF8 string one character at a time. It is passed a pointer
|
||||
* to the string and the length of the string. It sets 'value' to the value of
|
||||
* the current character. It returns the number of characters read or a
|
||||
* negative error code:
|
||||
* -1 = string too short
|
||||
* -2 = illegal character
|
||||
* -3 = subsequent characters not of the form 10xxxxxx
|
||||
* -4 = character encoded incorrectly (not minimal length).
|
||||
*/
|
||||
|
||||
int UTF8_getc(const unsigned char *str, int len, unsigned long *val)
|
||||
{
|
||||
const unsigned char *p;
|
||||
unsigned long value;
|
||||
int ret;
|
||||
if (len <= 0)
|
||||
return 0;
|
||||
p = str;
|
||||
|
||||
/* Check syntax and work out the encoded value (if correct) */
|
||||
if ((*p & 0x80) == 0) {
|
||||
value = *p++ & 0x7f;
|
||||
ret = 1;
|
||||
} else if ((*p & 0xe0) == 0xc0) {
|
||||
if (len < 2)
|
||||
return -1;
|
||||
if ((p[1] & 0xc0) != 0x80)
|
||||
return -3;
|
||||
value = (*p++ & 0x1f) << 6;
|
||||
value |= *p++ & 0x3f;
|
||||
if (value < 0x80)
|
||||
return -4;
|
||||
ret = 2;
|
||||
} else if ((*p & 0xf0) == 0xe0) {
|
||||
if (len < 3)
|
||||
return -1;
|
||||
if (((p[1] & 0xc0) != 0x80)
|
||||
|| ((p[2] & 0xc0) != 0x80))
|
||||
return -3;
|
||||
value = (*p++ & 0xf) << 12;
|
||||
value |= (*p++ & 0x3f) << 6;
|
||||
value |= *p++ & 0x3f;
|
||||
if (value < 0x800)
|
||||
return -4;
|
||||
ret = 3;
|
||||
} else if ((*p & 0xf8) == 0xf0) {
|
||||
if (len < 4)
|
||||
return -1;
|
||||
if (((p[1] & 0xc0) != 0x80)
|
||||
|| ((p[2] & 0xc0) != 0x80)
|
||||
|| ((p[3] & 0xc0) != 0x80))
|
||||
return -3;
|
||||
value = ((unsigned long)(*p++ & 0x7)) << 18;
|
||||
value |= (*p++ & 0x3f) << 12;
|
||||
value |= (*p++ & 0x3f) << 6;
|
||||
value |= *p++ & 0x3f;
|
||||
if (value < 0x10000)
|
||||
return -4;
|
||||
ret = 4;
|
||||
} else if ((*p & 0xfc) == 0xf8) {
|
||||
if (len < 5)
|
||||
return -1;
|
||||
if (((p[1] & 0xc0) != 0x80)
|
||||
|| ((p[2] & 0xc0) != 0x80)
|
||||
|| ((p[3] & 0xc0) != 0x80)
|
||||
|| ((p[4] & 0xc0) != 0x80))
|
||||
return -3;
|
||||
value = ((unsigned long)(*p++ & 0x3)) << 24;
|
||||
value |= ((unsigned long)(*p++ & 0x3f)) << 18;
|
||||
value |= ((unsigned long)(*p++ & 0x3f)) << 12;
|
||||
value |= (*p++ & 0x3f) << 6;
|
||||
value |= *p++ & 0x3f;
|
||||
if (value < 0x200000)
|
||||
return -4;
|
||||
ret = 5;
|
||||
} else if ((*p & 0xfe) == 0xfc) {
|
||||
if (len < 6)
|
||||
return -1;
|
||||
if (((p[1] & 0xc0) != 0x80)
|
||||
|| ((p[2] & 0xc0) != 0x80)
|
||||
|| ((p[3] & 0xc0) != 0x80)
|
||||
|| ((p[4] & 0xc0) != 0x80)
|
||||
|| ((p[5] & 0xc0) != 0x80))
|
||||
return -3;
|
||||
value = ((unsigned long)(*p++ & 0x1)) << 30;
|
||||
value |= ((unsigned long)(*p++ & 0x3f)) << 24;
|
||||
value |= ((unsigned long)(*p++ & 0x3f)) << 18;
|
||||
value |= ((unsigned long)(*p++ & 0x3f)) << 12;
|
||||
value |= (*p++ & 0x3f) << 6;
|
||||
value |= *p++ & 0x3f;
|
||||
if (value < 0x4000000)
|
||||
return -4;
|
||||
ret = 6;
|
||||
} else
|
||||
return -2;
|
||||
*val = value;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* This takes a character 'value' and writes the UTF8 encoded value in 'str'
|
||||
* where 'str' is a buffer containing 'len' characters. Returns the number of
|
||||
* characters written or -1 if 'len' is too small. 'str' can be set to NULL
|
||||
* in which case it just returns the number of characters. It will need at
|
||||
* most 6 characters.
|
||||
*/
|
||||
|
||||
int UTF8_putc(unsigned char *str, int len, unsigned long value)
|
||||
{
|
||||
if (!str)
|
||||
len = 6; /* Maximum we will need */
|
||||
else if (len <= 0)
|
||||
return -1;
|
||||
if (value < 0x80) {
|
||||
if (str)
|
||||
*str = (unsigned char)value;
|
||||
return 1;
|
||||
}
|
||||
if (value < 0x800) {
|
||||
if (len < 2)
|
||||
return -1;
|
||||
if (str) {
|
||||
*str++ = (unsigned char)(((value >> 6) & 0x1f) | 0xc0);
|
||||
*str = (unsigned char)((value & 0x3f) | 0x80);
|
||||
}
|
||||
return 2;
|
||||
}
|
||||
if (value < 0x10000) {
|
||||
if (len < 3)
|
||||
return -1;
|
||||
if (str) {
|
||||
*str++ = (unsigned char)(((value >> 12) & 0xf) | 0xe0);
|
||||
*str++ = (unsigned char)(((value >> 6) & 0x3f) | 0x80);
|
||||
*str = (unsigned char)((value & 0x3f) | 0x80);
|
||||
}
|
||||
return 3;
|
||||
}
|
||||
if (value < 0x200000) {
|
||||
if (len < 4)
|
||||
return -1;
|
||||
if (str) {
|
||||
*str++ = (unsigned char)(((value >> 18) & 0x7) | 0xf0);
|
||||
*str++ = (unsigned char)(((value >> 12) & 0x3f) | 0x80);
|
||||
*str++ = (unsigned char)(((value >> 6) & 0x3f) | 0x80);
|
||||
*str = (unsigned char)((value & 0x3f) | 0x80);
|
||||
}
|
||||
return 4;
|
||||
}
|
||||
if (value < 0x4000000) {
|
||||
if (len < 5)
|
||||
return -1;
|
||||
if (str) {
|
||||
*str++ = (unsigned char)(((value >> 24) & 0x3) | 0xf8);
|
||||
*str++ = (unsigned char)(((value >> 18) & 0x3f) | 0x80);
|
||||
*str++ = (unsigned char)(((value >> 12) & 0x3f) | 0x80);
|
||||
*str++ = (unsigned char)(((value >> 6) & 0x3f) | 0x80);
|
||||
*str = (unsigned char)((value & 0x3f) | 0x80);
|
||||
}
|
||||
return 5;
|
||||
}
|
||||
if (len < 6)
|
||||
return -1;
|
||||
if (str) {
|
||||
*str++ = (unsigned char)(((value >> 30) & 0x1) | 0xfc);
|
||||
*str++ = (unsigned char)(((value >> 24) & 0x3f) | 0x80);
|
||||
*str++ = (unsigned char)(((value >> 18) & 0x3f) | 0x80);
|
||||
*str++ = (unsigned char)(((value >> 12) & 0x3f) | 0x80);
|
||||
*str++ = (unsigned char)(((value >> 6) & 0x3f) | 0x80);
|
||||
*str = (unsigned char)((value & 0x3f) | 0x80);
|
||||
}
|
||||
return 6;
|
||||
}
|
||||
170
crypto/asn1/a_verify.c
Normal file
170
crypto/asn1/a_verify.c
Normal file
@@ -0,0 +1,170 @@
|
||||
/*
|
||||
* Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "internal/cryptlib.h"
|
||||
|
||||
#include <openssl/bn.h>
|
||||
#include <openssl/x509.h>
|
||||
#include <openssl/objects.h>
|
||||
#include <openssl/buffer.h>
|
||||
#include <openssl/evp.h>
|
||||
#include "internal/asn1_int.h"
|
||||
#include "internal/evp_int.h"
|
||||
|
||||
#ifndef NO_ASN1_OLD
|
||||
|
||||
int ASN1_verify(i2d_of_void *i2d, X509_ALGOR *a, ASN1_BIT_STRING *signature,
|
||||
char *data, EVP_PKEY *pkey)
|
||||
{
|
||||
EVP_MD_CTX *ctx = EVP_MD_CTX_new();
|
||||
const EVP_MD *type;
|
||||
unsigned char *p, *buf_in = NULL;
|
||||
int ret = -1, i, inl;
|
||||
|
||||
if (ctx == NULL) {
|
||||
ASN1err(ASN1_F_ASN1_VERIFY, ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
i = OBJ_obj2nid(a->algorithm);
|
||||
type = EVP_get_digestbyname(OBJ_nid2sn(i));
|
||||
if (type == NULL) {
|
||||
ASN1err(ASN1_F_ASN1_VERIFY, ASN1_R_UNKNOWN_MESSAGE_DIGEST_ALGORITHM);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (signature->type == V_ASN1_BIT_STRING && signature->flags & 0x7) {
|
||||
ASN1err(ASN1_F_ASN1_VERIFY, ASN1_R_INVALID_BIT_STRING_BITS_LEFT);
|
||||
goto err;
|
||||
}
|
||||
|
||||
inl = i2d(data, NULL);
|
||||
buf_in = OPENSSL_malloc((unsigned int)inl);
|
||||
if (buf_in == NULL) {
|
||||
ASN1err(ASN1_F_ASN1_VERIFY, ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
p = buf_in;
|
||||
|
||||
i2d(data, &p);
|
||||
ret = EVP_VerifyInit_ex(ctx, type, NULL)
|
||||
&& EVP_VerifyUpdate(ctx, (unsigned char *)buf_in, inl);
|
||||
|
||||
OPENSSL_clear_free(buf_in, (unsigned int)inl);
|
||||
|
||||
if (!ret) {
|
||||
ASN1err(ASN1_F_ASN1_VERIFY, ERR_R_EVP_LIB);
|
||||
goto err;
|
||||
}
|
||||
ret = -1;
|
||||
|
||||
if (EVP_VerifyFinal(ctx, (unsigned char *)signature->data,
|
||||
(unsigned int)signature->length, pkey) <= 0) {
|
||||
ASN1err(ASN1_F_ASN1_VERIFY, ERR_R_EVP_LIB);
|
||||
ret = 0;
|
||||
goto err;
|
||||
}
|
||||
ret = 1;
|
||||
err:
|
||||
EVP_MD_CTX_free(ctx);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
int ASN1_item_verify(const ASN1_ITEM *it, X509_ALGOR *a,
|
||||
ASN1_BIT_STRING *signature, void *asn, EVP_PKEY *pkey)
|
||||
{
|
||||
EVP_MD_CTX *ctx = NULL;
|
||||
unsigned char *buf_in = NULL;
|
||||
int ret = -1, inl = 0;
|
||||
|
||||
int mdnid, pknid;
|
||||
|
||||
if (!pkey) {
|
||||
ASN1err(ASN1_F_ASN1_ITEM_VERIFY, ERR_R_PASSED_NULL_PARAMETER);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (signature->type == V_ASN1_BIT_STRING && signature->flags & 0x7) {
|
||||
ASN1err(ASN1_F_ASN1_ITEM_VERIFY, ASN1_R_INVALID_BIT_STRING_BITS_LEFT);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ctx = EVP_MD_CTX_new();
|
||||
if (ctx == NULL) {
|
||||
ASN1err(ASN1_F_ASN1_ITEM_VERIFY, ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Convert signature OID into digest and public key OIDs */
|
||||
if (!OBJ_find_sigid_algs(OBJ_obj2nid(a->algorithm), &mdnid, &pknid)) {
|
||||
ASN1err(ASN1_F_ASN1_ITEM_VERIFY, ASN1_R_UNKNOWN_SIGNATURE_ALGORITHM);
|
||||
goto err;
|
||||
}
|
||||
if (mdnid == NID_undef) {
|
||||
if (!pkey->ameth || !pkey->ameth->item_verify) {
|
||||
ASN1err(ASN1_F_ASN1_ITEM_VERIFY,
|
||||
ASN1_R_UNKNOWN_SIGNATURE_ALGORITHM);
|
||||
goto err;
|
||||
}
|
||||
ret = pkey->ameth->item_verify(ctx, it, asn, a, signature, pkey);
|
||||
/*
|
||||
* Return value of 2 means carry on, anything else means we exit
|
||||
* straight away: either a fatal error of the underlying verification
|
||||
* routine handles all verification.
|
||||
*/
|
||||
if (ret != 2)
|
||||
goto err;
|
||||
ret = -1;
|
||||
} else {
|
||||
const EVP_MD *type;
|
||||
type = EVP_get_digestbynid(mdnid);
|
||||
if (type == NULL) {
|
||||
ASN1err(ASN1_F_ASN1_ITEM_VERIFY,
|
||||
ASN1_R_UNKNOWN_MESSAGE_DIGEST_ALGORITHM);
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Check public key OID matches public key type */
|
||||
if (EVP_PKEY_type(pknid) != pkey->ameth->pkey_id) {
|
||||
ASN1err(ASN1_F_ASN1_ITEM_VERIFY, ASN1_R_WRONG_PUBLIC_KEY_TYPE);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!EVP_DigestVerifyInit(ctx, NULL, type, NULL, pkey)) {
|
||||
ASN1err(ASN1_F_ASN1_ITEM_VERIFY, ERR_R_EVP_LIB);
|
||||
ret = 0;
|
||||
goto err;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
inl = ASN1_item_i2d(asn, &buf_in, it);
|
||||
|
||||
if (buf_in == NULL) {
|
||||
ASN1err(ASN1_F_ASN1_ITEM_VERIFY, ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = EVP_DigestVerify(ctx, signature->data, (size_t)signature->length,
|
||||
buf_in, inl);
|
||||
if (ret <= 0) {
|
||||
ASN1err(ASN1_F_ASN1_ITEM_VERIFY, ERR_R_EVP_LIB);
|
||||
goto err;
|
||||
}
|
||||
ret = 1;
|
||||
err:
|
||||
OPENSSL_clear_free(buf_in, (unsigned int)inl);
|
||||
EVP_MD_CTX_free(ctx);
|
||||
return ret;
|
||||
}
|
||||
447
crypto/asn1/ameth_lib.c
Normal file
447
crypto/asn1/ameth_lib.c
Normal file
@@ -0,0 +1,447 @@
|
||||
/*
|
||||
* Copyright 2006-2018 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#include "e_os.h" /* for strncasecmp */
|
||||
#include "internal/cryptlib.h"
|
||||
#include <stdio.h>
|
||||
#include <openssl/asn1t.h>
|
||||
#include <openssl/x509.h>
|
||||
#include <openssl/engine.h>
|
||||
#include "internal/asn1_int.h"
|
||||
#include "internal/evp_int.h"
|
||||
|
||||
#include "standard_methods.h"
|
||||
|
||||
typedef int sk_cmp_fn_type(const char *const *a, const char *const *b);
|
||||
static STACK_OF(EVP_PKEY_ASN1_METHOD) *app_methods = NULL;
|
||||
|
||||
DECLARE_OBJ_BSEARCH_CMP_FN(const EVP_PKEY_ASN1_METHOD *,
|
||||
const EVP_PKEY_ASN1_METHOD *, ameth);
|
||||
|
||||
static int ameth_cmp(const EVP_PKEY_ASN1_METHOD *const *a,
|
||||
const EVP_PKEY_ASN1_METHOD *const *b)
|
||||
{
|
||||
return ((*a)->pkey_id - (*b)->pkey_id);
|
||||
}
|
||||
|
||||
IMPLEMENT_OBJ_BSEARCH_CMP_FN(const EVP_PKEY_ASN1_METHOD *,
|
||||
const EVP_PKEY_ASN1_METHOD *, ameth);
|
||||
|
||||
int EVP_PKEY_asn1_get_count(void)
|
||||
{
|
||||
int num = OSSL_NELEM(standard_methods);
|
||||
if (app_methods)
|
||||
num += sk_EVP_PKEY_ASN1_METHOD_num(app_methods);
|
||||
return num;
|
||||
}
|
||||
|
||||
const EVP_PKEY_ASN1_METHOD *EVP_PKEY_asn1_get0(int idx)
|
||||
{
|
||||
int num = OSSL_NELEM(standard_methods);
|
||||
if (idx < 0)
|
||||
return NULL;
|
||||
if (idx < num)
|
||||
return standard_methods[idx];
|
||||
idx -= num;
|
||||
return sk_EVP_PKEY_ASN1_METHOD_value(app_methods, idx);
|
||||
}
|
||||
|
||||
static const EVP_PKEY_ASN1_METHOD *pkey_asn1_find(int type)
|
||||
{
|
||||
EVP_PKEY_ASN1_METHOD tmp;
|
||||
const EVP_PKEY_ASN1_METHOD *t = &tmp, **ret;
|
||||
tmp.pkey_id = type;
|
||||
if (app_methods) {
|
||||
int idx;
|
||||
idx = sk_EVP_PKEY_ASN1_METHOD_find(app_methods, &tmp);
|
||||
if (idx >= 0)
|
||||
return sk_EVP_PKEY_ASN1_METHOD_value(app_methods, idx);
|
||||
}
|
||||
ret = OBJ_bsearch_ameth(&t, standard_methods, OSSL_NELEM(standard_methods));
|
||||
if (!ret || !*ret)
|
||||
return NULL;
|
||||
return *ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Find an implementation of an ASN1 algorithm. If 'pe' is not NULL also
|
||||
* search through engines and set *pe to a functional reference to the engine
|
||||
* implementing 'type' or NULL if no engine implements it.
|
||||
*/
|
||||
|
||||
const EVP_PKEY_ASN1_METHOD *EVP_PKEY_asn1_find(ENGINE **pe, int type)
|
||||
{
|
||||
const EVP_PKEY_ASN1_METHOD *t;
|
||||
|
||||
for (;;) {
|
||||
t = pkey_asn1_find(type);
|
||||
if (!t || !(t->pkey_flags & ASN1_PKEY_ALIAS))
|
||||
break;
|
||||
type = t->pkey_base_id;
|
||||
}
|
||||
if (pe) {
|
||||
#ifndef OPENSSL_NO_ENGINE
|
||||
ENGINE *e;
|
||||
/* type will contain the final unaliased type */
|
||||
e = ENGINE_get_pkey_asn1_meth_engine(type);
|
||||
if (e) {
|
||||
*pe = e;
|
||||
return ENGINE_get_pkey_asn1_meth(e, type);
|
||||
}
|
||||
#endif
|
||||
*pe = NULL;
|
||||
}
|
||||
return t;
|
||||
}
|
||||
|
||||
const EVP_PKEY_ASN1_METHOD *EVP_PKEY_asn1_find_str(ENGINE **pe,
|
||||
const char *str, int len)
|
||||
{
|
||||
int i;
|
||||
const EVP_PKEY_ASN1_METHOD *ameth = NULL;
|
||||
|
||||
if (len == -1)
|
||||
len = strlen(str);
|
||||
if (pe) {
|
||||
#ifndef OPENSSL_NO_ENGINE
|
||||
ENGINE *e;
|
||||
ameth = ENGINE_pkey_asn1_find_str(&e, str, len);
|
||||
if (ameth) {
|
||||
/*
|
||||
* Convert structural into functional reference
|
||||
*/
|
||||
if (!ENGINE_init(e))
|
||||
ameth = NULL;
|
||||
ENGINE_free(e);
|
||||
*pe = e;
|
||||
return ameth;
|
||||
}
|
||||
#endif
|
||||
*pe = NULL;
|
||||
}
|
||||
for (i = EVP_PKEY_asn1_get_count(); i-- > 0; ) {
|
||||
ameth = EVP_PKEY_asn1_get0(i);
|
||||
if (ameth->pkey_flags & ASN1_PKEY_ALIAS)
|
||||
continue;
|
||||
if ((int)strlen(ameth->pem_str) == len
|
||||
&& strncasecmp(ameth->pem_str, str, len) == 0)
|
||||
return ameth;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int EVP_PKEY_asn1_add0(const EVP_PKEY_ASN1_METHOD *ameth)
|
||||
{
|
||||
EVP_PKEY_ASN1_METHOD tmp = { 0, };
|
||||
|
||||
if (app_methods == NULL) {
|
||||
app_methods = sk_EVP_PKEY_ASN1_METHOD_new(ameth_cmp);
|
||||
if (app_methods == NULL)
|
||||
return 0;
|
||||
}
|
||||
|
||||
tmp.pkey_id = ameth->pkey_id;
|
||||
if (sk_EVP_PKEY_ASN1_METHOD_find(app_methods, &tmp) >= 0) {
|
||||
EVPerr(EVP_F_EVP_PKEY_ASN1_ADD0,
|
||||
EVP_R_PKEY_APPLICATION_ASN1_METHOD_ALREADY_REGISTERED);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!sk_EVP_PKEY_ASN1_METHOD_push(app_methods, ameth))
|
||||
return 0;
|
||||
sk_EVP_PKEY_ASN1_METHOD_sort(app_methods);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int EVP_PKEY_asn1_add_alias(int to, int from)
|
||||
{
|
||||
EVP_PKEY_ASN1_METHOD *ameth;
|
||||
ameth = EVP_PKEY_asn1_new(from, ASN1_PKEY_ALIAS, NULL, NULL);
|
||||
if (ameth == NULL)
|
||||
return 0;
|
||||
ameth->pkey_base_id = to;
|
||||
if (!EVP_PKEY_asn1_add0(ameth)) {
|
||||
EVP_PKEY_asn1_free(ameth);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int EVP_PKEY_asn1_get0_info(int *ppkey_id, int *ppkey_base_id,
|
||||
int *ppkey_flags, const char **pinfo,
|
||||
const char **ppem_str,
|
||||
const EVP_PKEY_ASN1_METHOD *ameth)
|
||||
{
|
||||
if (!ameth)
|
||||
return 0;
|
||||
if (ppkey_id)
|
||||
*ppkey_id = ameth->pkey_id;
|
||||
if (ppkey_base_id)
|
||||
*ppkey_base_id = ameth->pkey_base_id;
|
||||
if (ppkey_flags)
|
||||
*ppkey_flags = ameth->pkey_flags;
|
||||
if (pinfo)
|
||||
*pinfo = ameth->info;
|
||||
if (ppem_str)
|
||||
*ppem_str = ameth->pem_str;
|
||||
return 1;
|
||||
}
|
||||
|
||||
const EVP_PKEY_ASN1_METHOD *EVP_PKEY_get0_asn1(const EVP_PKEY *pkey)
|
||||
{
|
||||
return pkey->ameth;
|
||||
}
|
||||
|
||||
EVP_PKEY_ASN1_METHOD *EVP_PKEY_asn1_new(int id, int flags,
|
||||
const char *pem_str, const char *info)
|
||||
{
|
||||
EVP_PKEY_ASN1_METHOD *ameth = OPENSSL_zalloc(sizeof(*ameth));
|
||||
|
||||
if (ameth == NULL)
|
||||
return NULL;
|
||||
|
||||
ameth->pkey_id = id;
|
||||
ameth->pkey_base_id = id;
|
||||
ameth->pkey_flags = flags | ASN1_PKEY_DYNAMIC;
|
||||
|
||||
if (info) {
|
||||
ameth->info = OPENSSL_strdup(info);
|
||||
if (!ameth->info)
|
||||
goto err;
|
||||
}
|
||||
|
||||
/*
|
||||
* One of the following must be true:
|
||||
*
|
||||
* pem_str == NULL AND ASN1_PKEY_ALIAS is set
|
||||
* pem_str != NULL AND ASN1_PKEY_ALIAS is clear
|
||||
*
|
||||
* Anything else is an error and may lead to a corrupt ASN1 method table
|
||||
*/
|
||||
if (!((pem_str == NULL && (flags & ASN1_PKEY_ALIAS) != 0)
|
||||
|| (pem_str != NULL && (flags & ASN1_PKEY_ALIAS) == 0)))
|
||||
goto err;
|
||||
|
||||
if (pem_str) {
|
||||
ameth->pem_str = OPENSSL_strdup(pem_str);
|
||||
if (!ameth->pem_str)
|
||||
goto err;
|
||||
}
|
||||
|
||||
return ameth;
|
||||
|
||||
err:
|
||||
EVP_PKEY_asn1_free(ameth);
|
||||
return NULL;
|
||||
|
||||
}
|
||||
|
||||
void EVP_PKEY_asn1_copy(EVP_PKEY_ASN1_METHOD *dst,
|
||||
const EVP_PKEY_ASN1_METHOD *src)
|
||||
{
|
||||
|
||||
dst->pub_decode = src->pub_decode;
|
||||
dst->pub_encode = src->pub_encode;
|
||||
dst->pub_cmp = src->pub_cmp;
|
||||
dst->pub_print = src->pub_print;
|
||||
|
||||
dst->priv_decode = src->priv_decode;
|
||||
dst->priv_encode = src->priv_encode;
|
||||
dst->priv_print = src->priv_print;
|
||||
|
||||
dst->old_priv_encode = src->old_priv_encode;
|
||||
dst->old_priv_decode = src->old_priv_decode;
|
||||
|
||||
dst->pkey_size = src->pkey_size;
|
||||
dst->pkey_bits = src->pkey_bits;
|
||||
|
||||
dst->param_decode = src->param_decode;
|
||||
dst->param_encode = src->param_encode;
|
||||
dst->param_missing = src->param_missing;
|
||||
dst->param_copy = src->param_copy;
|
||||
dst->param_cmp = src->param_cmp;
|
||||
dst->param_print = src->param_print;
|
||||
|
||||
dst->pkey_free = src->pkey_free;
|
||||
dst->pkey_ctrl = src->pkey_ctrl;
|
||||
|
||||
dst->item_sign = src->item_sign;
|
||||
dst->item_verify = src->item_verify;
|
||||
|
||||
dst->siginf_set = src->siginf_set;
|
||||
|
||||
dst->pkey_check = src->pkey_check;
|
||||
|
||||
}
|
||||
|
||||
void EVP_PKEY_asn1_free(EVP_PKEY_ASN1_METHOD *ameth)
|
||||
{
|
||||
if (ameth && (ameth->pkey_flags & ASN1_PKEY_DYNAMIC)) {
|
||||
OPENSSL_free(ameth->pem_str);
|
||||
OPENSSL_free(ameth->info);
|
||||
OPENSSL_free(ameth);
|
||||
}
|
||||
}
|
||||
|
||||
void EVP_PKEY_asn1_set_public(EVP_PKEY_ASN1_METHOD *ameth,
|
||||
int (*pub_decode) (EVP_PKEY *pk,
|
||||
X509_PUBKEY *pub),
|
||||
int (*pub_encode) (X509_PUBKEY *pub,
|
||||
const EVP_PKEY *pk),
|
||||
int (*pub_cmp) (const EVP_PKEY *a,
|
||||
const EVP_PKEY *b),
|
||||
int (*pub_print) (BIO *out,
|
||||
const EVP_PKEY *pkey,
|
||||
int indent, ASN1_PCTX *pctx),
|
||||
int (*pkey_size) (const EVP_PKEY *pk),
|
||||
int (*pkey_bits) (const EVP_PKEY *pk))
|
||||
{
|
||||
ameth->pub_decode = pub_decode;
|
||||
ameth->pub_encode = pub_encode;
|
||||
ameth->pub_cmp = pub_cmp;
|
||||
ameth->pub_print = pub_print;
|
||||
ameth->pkey_size = pkey_size;
|
||||
ameth->pkey_bits = pkey_bits;
|
||||
}
|
||||
|
||||
void EVP_PKEY_asn1_set_private(EVP_PKEY_ASN1_METHOD *ameth,
|
||||
int (*priv_decode) (EVP_PKEY *pk,
|
||||
const PKCS8_PRIV_KEY_INFO
|
||||
*p8inf),
|
||||
int (*priv_encode) (PKCS8_PRIV_KEY_INFO *p8,
|
||||
const EVP_PKEY *pk),
|
||||
int (*priv_print) (BIO *out,
|
||||
const EVP_PKEY *pkey,
|
||||
int indent,
|
||||
ASN1_PCTX *pctx))
|
||||
{
|
||||
ameth->priv_decode = priv_decode;
|
||||
ameth->priv_encode = priv_encode;
|
||||
ameth->priv_print = priv_print;
|
||||
}
|
||||
|
||||
void EVP_PKEY_asn1_set_param(EVP_PKEY_ASN1_METHOD *ameth,
|
||||
int (*param_decode) (EVP_PKEY *pkey,
|
||||
const unsigned char **pder,
|
||||
int derlen),
|
||||
int (*param_encode) (const EVP_PKEY *pkey,
|
||||
unsigned char **pder),
|
||||
int (*param_missing) (const EVP_PKEY *pk),
|
||||
int (*param_copy) (EVP_PKEY *to,
|
||||
const EVP_PKEY *from),
|
||||
int (*param_cmp) (const EVP_PKEY *a,
|
||||
const EVP_PKEY *b),
|
||||
int (*param_print) (BIO *out,
|
||||
const EVP_PKEY *pkey,
|
||||
int indent, ASN1_PCTX *pctx))
|
||||
{
|
||||
ameth->param_decode = param_decode;
|
||||
ameth->param_encode = param_encode;
|
||||
ameth->param_missing = param_missing;
|
||||
ameth->param_copy = param_copy;
|
||||
ameth->param_cmp = param_cmp;
|
||||
ameth->param_print = param_print;
|
||||
}
|
||||
|
||||
void EVP_PKEY_asn1_set_free(EVP_PKEY_ASN1_METHOD *ameth,
|
||||
void (*pkey_free) (EVP_PKEY *pkey))
|
||||
{
|
||||
ameth->pkey_free = pkey_free;
|
||||
}
|
||||
|
||||
void EVP_PKEY_asn1_set_ctrl(EVP_PKEY_ASN1_METHOD *ameth,
|
||||
int (*pkey_ctrl) (EVP_PKEY *pkey, int op,
|
||||
long arg1, void *arg2))
|
||||
{
|
||||
ameth->pkey_ctrl = pkey_ctrl;
|
||||
}
|
||||
|
||||
void EVP_PKEY_asn1_set_security_bits(EVP_PKEY_ASN1_METHOD *ameth,
|
||||
int (*pkey_security_bits) (const EVP_PKEY
|
||||
*pk))
|
||||
{
|
||||
ameth->pkey_security_bits = pkey_security_bits;
|
||||
}
|
||||
|
||||
void EVP_PKEY_asn1_set_item(EVP_PKEY_ASN1_METHOD *ameth,
|
||||
int (*item_verify) (EVP_MD_CTX *ctx,
|
||||
const ASN1_ITEM *it,
|
||||
void *asn,
|
||||
X509_ALGOR *a,
|
||||
ASN1_BIT_STRING *sig,
|
||||
EVP_PKEY *pkey),
|
||||
int (*item_sign) (EVP_MD_CTX *ctx,
|
||||
const ASN1_ITEM *it,
|
||||
void *asn,
|
||||
X509_ALGOR *alg1,
|
||||
X509_ALGOR *alg2,
|
||||
ASN1_BIT_STRING *sig))
|
||||
{
|
||||
ameth->item_sign = item_sign;
|
||||
ameth->item_verify = item_verify;
|
||||
}
|
||||
|
||||
void EVP_PKEY_asn1_set_siginf(EVP_PKEY_ASN1_METHOD *ameth,
|
||||
int (*siginf_set) (X509_SIG_INFO *siginf,
|
||||
const X509_ALGOR *alg,
|
||||
const ASN1_STRING *sig))
|
||||
{
|
||||
ameth->siginf_set = siginf_set;
|
||||
}
|
||||
|
||||
void EVP_PKEY_asn1_set_check(EVP_PKEY_ASN1_METHOD *ameth,
|
||||
int (*pkey_check) (const EVP_PKEY *pk))
|
||||
{
|
||||
ameth->pkey_check = pkey_check;
|
||||
}
|
||||
|
||||
void EVP_PKEY_asn1_set_public_check(EVP_PKEY_ASN1_METHOD *ameth,
|
||||
int (*pkey_pub_check) (const EVP_PKEY *pk))
|
||||
{
|
||||
ameth->pkey_public_check = pkey_pub_check;
|
||||
}
|
||||
|
||||
void EVP_PKEY_asn1_set_param_check(EVP_PKEY_ASN1_METHOD *ameth,
|
||||
int (*pkey_param_check) (const EVP_PKEY *pk))
|
||||
{
|
||||
ameth->pkey_param_check = pkey_param_check;
|
||||
}
|
||||
|
||||
void EVP_PKEY_asn1_set_set_priv_key(EVP_PKEY_ASN1_METHOD *ameth,
|
||||
int (*set_priv_key) (EVP_PKEY *pk,
|
||||
const unsigned char
|
||||
*priv,
|
||||
size_t len))
|
||||
{
|
||||
ameth->set_priv_key = set_priv_key;
|
||||
}
|
||||
|
||||
void EVP_PKEY_asn1_set_set_pub_key(EVP_PKEY_ASN1_METHOD *ameth,
|
||||
int (*set_pub_key) (EVP_PKEY *pk,
|
||||
const unsigned char *pub,
|
||||
size_t len))
|
||||
{
|
||||
ameth->set_pub_key = set_pub_key;
|
||||
}
|
||||
|
||||
void EVP_PKEY_asn1_set_get_priv_key(EVP_PKEY_ASN1_METHOD *ameth,
|
||||
int (*get_priv_key) (const EVP_PKEY *pk,
|
||||
unsigned char *priv,
|
||||
size_t *len))
|
||||
{
|
||||
ameth->get_priv_key = get_priv_key;
|
||||
}
|
||||
|
||||
void EVP_PKEY_asn1_set_get_pub_key(EVP_PKEY_ASN1_METHOD *ameth,
|
||||
int (*get_pub_key) (const EVP_PKEY *pk,
|
||||
unsigned char *pub,
|
||||
size_t *len))
|
||||
{
|
||||
ameth->get_pub_key = get_pub_key;
|
||||
}
|
||||
350
crypto/asn1/asn1_err.c
Normal file
350
crypto/asn1/asn1_err.c
Normal file
@@ -0,0 +1,350 @@
|
||||
/*
|
||||
* Generated by util/mkerr.pl DO NOT EDIT
|
||||
* Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/asn1err.h>
|
||||
|
||||
#ifndef OPENSSL_NO_ERR
|
||||
|
||||
static const ERR_STRING_DATA ASN1_str_functs[] = {
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_A2D_ASN1_OBJECT, 0), "a2d_ASN1_OBJECT"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_A2I_ASN1_INTEGER, 0), "a2i_ASN1_INTEGER"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_A2I_ASN1_STRING, 0), "a2i_ASN1_STRING"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_APPEND_EXP, 0), "append_exp"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_BIO_INIT, 0), "asn1_bio_init"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_BIT_STRING_SET_BIT, 0),
|
||||
"ASN1_BIT_STRING_set_bit"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_CB, 0), "asn1_cb"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_CHECK_TLEN, 0), "asn1_check_tlen"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_COLLECT, 0), "asn1_collect"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_D2I_EX_PRIMITIVE, 0),
|
||||
"asn1_d2i_ex_primitive"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_D2I_FP, 0), "ASN1_d2i_fp"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_D2I_READ_BIO, 0), "asn1_d2i_read_bio"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_DIGEST, 0), "ASN1_digest"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_DO_ADB, 0), "asn1_do_adb"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_DO_LOCK, 0), "asn1_do_lock"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_DUP, 0), "ASN1_dup"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_ENC_SAVE, 0), "asn1_enc_save"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_EX_C2I, 0), "asn1_ex_c2i"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_FIND_END, 0), "asn1_find_end"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_GENERALIZEDTIME_ADJ, 0),
|
||||
"ASN1_GENERALIZEDTIME_adj"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_GENERATE_V3, 0), "ASN1_generate_v3"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_GET_INT64, 0), "asn1_get_int64"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_GET_OBJECT, 0), "ASN1_get_object"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_GET_UINT64, 0), "asn1_get_uint64"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_I2D_BIO, 0), "ASN1_i2d_bio"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_I2D_FP, 0), "ASN1_i2d_fp"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_ITEM_D2I_FP, 0), "ASN1_item_d2i_fp"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_ITEM_DUP, 0), "ASN1_item_dup"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_ITEM_EMBED_D2I, 0),
|
||||
"asn1_item_embed_d2i"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_ITEM_EMBED_NEW, 0),
|
||||
"asn1_item_embed_new"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_ITEM_FLAGS_I2D, 0),
|
||||
"asn1_item_flags_i2d"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_ITEM_I2D_BIO, 0), "ASN1_item_i2d_bio"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_ITEM_I2D_FP, 0), "ASN1_item_i2d_fp"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_ITEM_PACK, 0), "ASN1_item_pack"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_ITEM_SIGN, 0), "ASN1_item_sign"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_ITEM_SIGN_CTX, 0),
|
||||
"ASN1_item_sign_ctx"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_ITEM_UNPACK, 0), "ASN1_item_unpack"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_ITEM_VERIFY, 0), "ASN1_item_verify"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_MBSTRING_NCOPY, 0),
|
||||
"ASN1_mbstring_ncopy"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_OBJECT_NEW, 0), "ASN1_OBJECT_new"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_OUTPUT_DATA, 0), "asn1_output_data"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_PCTX_NEW, 0), "ASN1_PCTX_new"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_PRIMITIVE_NEW, 0),
|
||||
"asn1_primitive_new"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_SCTX_NEW, 0), "ASN1_SCTX_new"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_SIGN, 0), "ASN1_sign"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_STR2TYPE, 0), "asn1_str2type"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_STRING_GET_INT64, 0),
|
||||
"asn1_string_get_int64"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_STRING_GET_UINT64, 0),
|
||||
"asn1_string_get_uint64"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_STRING_SET, 0), "ASN1_STRING_set"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_STRING_TABLE_ADD, 0),
|
||||
"ASN1_STRING_TABLE_add"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_STRING_TO_BN, 0), "asn1_string_to_bn"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_STRING_TYPE_NEW, 0),
|
||||
"ASN1_STRING_type_new"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_TEMPLATE_EX_D2I, 0),
|
||||
"asn1_template_ex_d2i"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_TEMPLATE_NEW, 0), "asn1_template_new"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_TEMPLATE_NOEXP_D2I, 0),
|
||||
"asn1_template_noexp_d2i"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_TIME_ADJ, 0), "ASN1_TIME_adj"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_TYPE_GET_INT_OCTETSTRING, 0),
|
||||
"ASN1_TYPE_get_int_octetstring"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_TYPE_GET_OCTETSTRING, 0),
|
||||
"ASN1_TYPE_get_octetstring"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_UTCTIME_ADJ, 0), "ASN1_UTCTIME_adj"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_VERIFY, 0), "ASN1_verify"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_B64_READ_ASN1, 0), "b64_read_asn1"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_B64_WRITE_ASN1, 0), "B64_write_ASN1"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_BIO_NEW_NDEF, 0), "BIO_new_NDEF"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_BITSTR_CB, 0), "bitstr_cb"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_BN_TO_ASN1_STRING, 0), "bn_to_asn1_string"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_C2I_ASN1_BIT_STRING, 0),
|
||||
"c2i_ASN1_BIT_STRING"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_C2I_ASN1_INTEGER, 0), "c2i_ASN1_INTEGER"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_C2I_ASN1_OBJECT, 0), "c2i_ASN1_OBJECT"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_C2I_IBUF, 0), "c2i_ibuf"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_C2I_UINT64_INT, 0), "c2i_uint64_int"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_COLLECT_DATA, 0), "collect_data"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_D2I_ASN1_OBJECT, 0), "d2i_ASN1_OBJECT"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_D2I_ASN1_UINTEGER, 0), "d2i_ASN1_UINTEGER"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_D2I_AUTOPRIVATEKEY, 0),
|
||||
"d2i_AutoPrivateKey"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_D2I_PRIVATEKEY, 0), "d2i_PrivateKey"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_D2I_PUBLICKEY, 0), "d2i_PublicKey"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_DO_BUF, 0), "do_buf"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_DO_CREATE, 0), "do_create"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_DO_DUMP, 0), "do_dump"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_DO_TCREATE, 0), "do_tcreate"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_I2A_ASN1_OBJECT, 0), "i2a_ASN1_OBJECT"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_I2D_ASN1_BIO_STREAM, 0),
|
||||
"i2d_ASN1_bio_stream"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_I2D_ASN1_OBJECT, 0), "i2d_ASN1_OBJECT"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_I2D_DSA_PUBKEY, 0), "i2d_DSA_PUBKEY"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_I2D_EC_PUBKEY, 0), "i2d_EC_PUBKEY"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_I2D_PRIVATEKEY, 0), "i2d_PrivateKey"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_I2D_PUBLICKEY, 0), "i2d_PublicKey"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_I2D_RSA_PUBKEY, 0), "i2d_RSA_PUBKEY"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_LONG_C2I, 0), "long_c2i"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_NDEF_PREFIX, 0), "ndef_prefix"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_NDEF_SUFFIX, 0), "ndef_suffix"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_OID_MODULE_INIT, 0), "oid_module_init"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_PARSE_TAGGING, 0), "parse_tagging"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_PKCS5_PBE2_SET_IV, 0), "PKCS5_pbe2_set_iv"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_PKCS5_PBE2_SET_SCRYPT, 0),
|
||||
"PKCS5_pbe2_set_scrypt"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_PKCS5_PBE_SET, 0), "PKCS5_pbe_set"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_PKCS5_PBE_SET0_ALGOR, 0),
|
||||
"PKCS5_pbe_set0_algor"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_PKCS5_PBKDF2_SET, 0), "PKCS5_pbkdf2_set"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_PKCS5_SCRYPT_SET, 0), "pkcs5_scrypt_set"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_SMIME_READ_ASN1, 0), "SMIME_read_ASN1"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_SMIME_TEXT, 0), "SMIME_text"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_STABLE_GET, 0), "stable_get"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_STBL_MODULE_INIT, 0), "stbl_module_init"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_UINT32_C2I, 0), "uint32_c2i"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_UINT32_NEW, 0), "uint32_new"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_UINT64_C2I, 0), "uint64_c2i"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_UINT64_NEW, 0), "uint64_new"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_X509_CRL_ADD0_REVOKED, 0),
|
||||
"X509_CRL_add0_revoked"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_X509_INFO_NEW, 0), "X509_INFO_new"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_X509_NAME_ENCODE, 0), "x509_name_encode"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_X509_NAME_EX_D2I, 0), "x509_name_ex_d2i"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_X509_NAME_EX_NEW, 0), "x509_name_ex_new"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_X509_PKEY_NEW, 0), "X509_PKEY_new"},
|
||||
{0, NULL}
|
||||
};
|
||||
|
||||
static const ERR_STRING_DATA ASN1_str_reasons[] = {
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_ADDING_OBJECT), "adding object"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_ASN1_PARSE_ERROR), "asn1 parse error"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_ASN1_SIG_PARSE_ERROR),
|
||||
"asn1 sig parse error"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_AUX_ERROR), "aux error"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_BAD_OBJECT_HEADER), "bad object header"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_BMPSTRING_IS_WRONG_LENGTH),
|
||||
"bmpstring is wrong length"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_BN_LIB), "bn lib"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_BOOLEAN_IS_WRONG_LENGTH),
|
||||
"boolean is wrong length"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_BUFFER_TOO_SMALL), "buffer too small"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_CIPHER_HAS_NO_OBJECT_IDENTIFIER),
|
||||
"cipher has no object identifier"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_CONTEXT_NOT_INITIALISED),
|
||||
"context not initialised"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_DATA_IS_WRONG), "data is wrong"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_DECODE_ERROR), "decode error"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_DEPTH_EXCEEDED), "depth exceeded"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_DIGEST_AND_KEY_TYPE_NOT_SUPPORTED),
|
||||
"digest and key type not supported"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_ENCODE_ERROR), "encode error"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_ERROR_GETTING_TIME),
|
||||
"error getting time"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_ERROR_LOADING_SECTION),
|
||||
"error loading section"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_ERROR_SETTING_CIPHER_PARAMS),
|
||||
"error setting cipher params"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_EXPECTING_AN_INTEGER),
|
||||
"expecting an integer"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_EXPECTING_AN_OBJECT),
|
||||
"expecting an object"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_EXPLICIT_LENGTH_MISMATCH),
|
||||
"explicit length mismatch"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_EXPLICIT_TAG_NOT_CONSTRUCTED),
|
||||
"explicit tag not constructed"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_FIELD_MISSING), "field missing"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_FIRST_NUM_TOO_LARGE),
|
||||
"first num too large"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_HEADER_TOO_LONG), "header too long"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_ILLEGAL_BITSTRING_FORMAT),
|
||||
"illegal bitstring format"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_ILLEGAL_BOOLEAN), "illegal boolean"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_ILLEGAL_CHARACTERS),
|
||||
"illegal characters"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_ILLEGAL_FORMAT), "illegal format"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_ILLEGAL_HEX), "illegal hex"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_ILLEGAL_IMPLICIT_TAG),
|
||||
"illegal implicit tag"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_ILLEGAL_INTEGER), "illegal integer"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_ILLEGAL_NEGATIVE_VALUE),
|
||||
"illegal negative value"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_ILLEGAL_NESTED_TAGGING),
|
||||
"illegal nested tagging"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_ILLEGAL_NULL), "illegal null"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_ILLEGAL_NULL_VALUE),
|
||||
"illegal null value"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_ILLEGAL_OBJECT), "illegal object"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_ILLEGAL_OPTIONAL_ANY),
|
||||
"illegal optional any"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_ILLEGAL_OPTIONS_ON_ITEM_TEMPLATE),
|
||||
"illegal options on item template"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_ILLEGAL_PADDING), "illegal padding"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_ILLEGAL_TAGGED_ANY),
|
||||
"illegal tagged any"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_ILLEGAL_TIME_VALUE),
|
||||
"illegal time value"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_ILLEGAL_ZERO_CONTENT),
|
||||
"illegal zero content"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_INTEGER_NOT_ASCII_FORMAT),
|
||||
"integer not ascii format"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_INTEGER_TOO_LARGE_FOR_LONG),
|
||||
"integer too large for long"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_INVALID_BIT_STRING_BITS_LEFT),
|
||||
"invalid bit string bits left"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_INVALID_BMPSTRING_LENGTH),
|
||||
"invalid bmpstring length"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_INVALID_DIGIT), "invalid digit"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_INVALID_MIME_TYPE), "invalid mime type"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_INVALID_MODIFIER), "invalid modifier"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_INVALID_NUMBER), "invalid number"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_INVALID_OBJECT_ENCODING),
|
||||
"invalid object encoding"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_INVALID_SCRYPT_PARAMETERS),
|
||||
"invalid scrypt parameters"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_INVALID_SEPARATOR), "invalid separator"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_INVALID_STRING_TABLE_VALUE),
|
||||
"invalid string table value"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_INVALID_UNIVERSALSTRING_LENGTH),
|
||||
"invalid universalstring length"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_INVALID_UTF8STRING),
|
||||
"invalid utf8string"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_INVALID_VALUE), "invalid value"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_LIST_ERROR), "list error"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_MIME_NO_CONTENT_TYPE),
|
||||
"mime no content type"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_MIME_PARSE_ERROR), "mime parse error"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_MIME_SIG_PARSE_ERROR),
|
||||
"mime sig parse error"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_MISSING_EOC), "missing eoc"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_MISSING_SECOND_NUMBER),
|
||||
"missing second number"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_MISSING_VALUE), "missing value"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_MSTRING_NOT_UNIVERSAL),
|
||||
"mstring not universal"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_MSTRING_WRONG_TAG), "mstring wrong tag"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_NESTED_ASN1_STRING),
|
||||
"nested asn1 string"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_NESTED_TOO_DEEP), "nested too deep"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_NON_HEX_CHARACTERS),
|
||||
"non hex characters"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_NOT_ASCII_FORMAT), "not ascii format"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_NOT_ENOUGH_DATA), "not enough data"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_NO_CONTENT_TYPE), "no content type"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_NO_MATCHING_CHOICE_TYPE),
|
||||
"no matching choice type"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_NO_MULTIPART_BODY_FAILURE),
|
||||
"no multipart body failure"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_NO_MULTIPART_BOUNDARY),
|
||||
"no multipart boundary"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_NO_SIG_CONTENT_TYPE),
|
||||
"no sig content type"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_NULL_IS_WRONG_LENGTH),
|
||||
"null is wrong length"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_OBJECT_NOT_ASCII_FORMAT),
|
||||
"object not ascii format"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_ODD_NUMBER_OF_CHARS),
|
||||
"odd number of chars"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_SECOND_NUMBER_TOO_LARGE),
|
||||
"second number too large"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_SEQUENCE_LENGTH_MISMATCH),
|
||||
"sequence length mismatch"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_SEQUENCE_NOT_CONSTRUCTED),
|
||||
"sequence not constructed"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_SEQUENCE_OR_SET_NEEDS_CONFIG),
|
||||
"sequence or set needs config"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_SHORT_LINE), "short line"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_SIG_INVALID_MIME_TYPE),
|
||||
"sig invalid mime type"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_STREAMING_NOT_SUPPORTED),
|
||||
"streaming not supported"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_STRING_TOO_LONG), "string too long"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_STRING_TOO_SHORT), "string too short"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_THE_ASN1_OBJECT_IDENTIFIER_IS_NOT_KNOWN_FOR_THIS_MD),
|
||||
"the asn1 object identifier is not known for this md"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_TIME_NOT_ASCII_FORMAT),
|
||||
"time not ascii format"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_TOO_LARGE), "too large"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_TOO_LONG), "too long"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_TOO_SMALL), "too small"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_TYPE_NOT_CONSTRUCTED),
|
||||
"type not constructed"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_TYPE_NOT_PRIMITIVE),
|
||||
"type not primitive"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_UNEXPECTED_EOC), "unexpected eoc"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_UNIVERSALSTRING_IS_WRONG_LENGTH),
|
||||
"universalstring is wrong length"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_UNKNOWN_FORMAT), "unknown format"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_UNKNOWN_MESSAGE_DIGEST_ALGORITHM),
|
||||
"unknown message digest algorithm"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_UNKNOWN_OBJECT_TYPE),
|
||||
"unknown object type"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_UNKNOWN_PUBLIC_KEY_TYPE),
|
||||
"unknown public key type"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_UNKNOWN_SIGNATURE_ALGORITHM),
|
||||
"unknown signature algorithm"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_UNKNOWN_TAG), "unknown tag"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_UNSUPPORTED_ANY_DEFINED_BY_TYPE),
|
||||
"unsupported any defined by type"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_UNSUPPORTED_CIPHER),
|
||||
"unsupported cipher"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_UNSUPPORTED_PUBLIC_KEY_TYPE),
|
||||
"unsupported public key type"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_UNSUPPORTED_TYPE), "unsupported type"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_WRONG_INTEGER_TYPE),
|
||||
"wrong integer type"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_WRONG_PUBLIC_KEY_TYPE),
|
||||
"wrong public key type"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_WRONG_TAG), "wrong tag"},
|
||||
{0, NULL}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
int ERR_load_ASN1_strings(void)
|
||||
{
|
||||
#ifndef OPENSSL_NO_ERR
|
||||
if (ERR_func_error_string(ASN1_str_functs[0].error) == NULL) {
|
||||
ERR_load_strings_const(ASN1_str_functs);
|
||||
ERR_load_strings_const(ASN1_str_reasons);
|
||||
}
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
789
crypto/asn1/asn1_gen.c
Normal file
789
crypto/asn1/asn1_gen.c
Normal file
@@ -0,0 +1,789 @@
|
||||
/*
|
||||
* Copyright 2002-2016 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#include "internal/cryptlib.h"
|
||||
#include <openssl/asn1.h>
|
||||
#include <openssl/x509v3.h>
|
||||
|
||||
#define ASN1_GEN_FLAG 0x10000
|
||||
#define ASN1_GEN_FLAG_IMP (ASN1_GEN_FLAG|1)
|
||||
#define ASN1_GEN_FLAG_EXP (ASN1_GEN_FLAG|2)
|
||||
#define ASN1_GEN_FLAG_TAG (ASN1_GEN_FLAG|3)
|
||||
#define ASN1_GEN_FLAG_BITWRAP (ASN1_GEN_FLAG|4)
|
||||
#define ASN1_GEN_FLAG_OCTWRAP (ASN1_GEN_FLAG|5)
|
||||
#define ASN1_GEN_FLAG_SEQWRAP (ASN1_GEN_FLAG|6)
|
||||
#define ASN1_GEN_FLAG_SETWRAP (ASN1_GEN_FLAG|7)
|
||||
#define ASN1_GEN_FLAG_FORMAT (ASN1_GEN_FLAG|8)
|
||||
|
||||
#define ASN1_GEN_STR(str,val) {str, sizeof(str) - 1, val}
|
||||
|
||||
#define ASN1_FLAG_EXP_MAX 20
|
||||
/* Maximum number of nested sequences */
|
||||
#define ASN1_GEN_SEQ_MAX_DEPTH 50
|
||||
|
||||
/* Input formats */
|
||||
|
||||
/* ASCII: default */
|
||||
#define ASN1_GEN_FORMAT_ASCII 1
|
||||
/* UTF8 */
|
||||
#define ASN1_GEN_FORMAT_UTF8 2
|
||||
/* Hex */
|
||||
#define ASN1_GEN_FORMAT_HEX 3
|
||||
/* List of bits */
|
||||
#define ASN1_GEN_FORMAT_BITLIST 4
|
||||
|
||||
struct tag_name_st {
|
||||
const char *strnam;
|
||||
int len;
|
||||
int tag;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
int exp_tag;
|
||||
int exp_class;
|
||||
int exp_constructed;
|
||||
int exp_pad;
|
||||
long exp_len;
|
||||
} tag_exp_type;
|
||||
|
||||
typedef struct {
|
||||
int imp_tag;
|
||||
int imp_class;
|
||||
int utype;
|
||||
int format;
|
||||
const char *str;
|
||||
tag_exp_type exp_list[ASN1_FLAG_EXP_MAX];
|
||||
int exp_count;
|
||||
} tag_exp_arg;
|
||||
|
||||
static ASN1_TYPE *generate_v3(const char *str, X509V3_CTX *cnf, int depth,
|
||||
int *perr);
|
||||
static int bitstr_cb(const char *elem, int len, void *bitstr);
|
||||
static int asn1_cb(const char *elem, int len, void *bitstr);
|
||||
static int append_exp(tag_exp_arg *arg, int exp_tag, int exp_class,
|
||||
int exp_constructed, int exp_pad, int imp_ok);
|
||||
static int parse_tagging(const char *vstart, int vlen, int *ptag,
|
||||
int *pclass);
|
||||
static ASN1_TYPE *asn1_multi(int utype, const char *section, X509V3_CTX *cnf,
|
||||
int depth, int *perr);
|
||||
static ASN1_TYPE *asn1_str2type(const char *str, int format, int utype);
|
||||
static int asn1_str2tag(const char *tagstr, int len);
|
||||
|
||||
ASN1_TYPE *ASN1_generate_nconf(const char *str, CONF *nconf)
|
||||
{
|
||||
X509V3_CTX cnf;
|
||||
|
||||
if (!nconf)
|
||||
return ASN1_generate_v3(str, NULL);
|
||||
|
||||
X509V3_set_nconf(&cnf, nconf);
|
||||
return ASN1_generate_v3(str, &cnf);
|
||||
}
|
||||
|
||||
ASN1_TYPE *ASN1_generate_v3(const char *str, X509V3_CTX *cnf)
|
||||
{
|
||||
int err = 0;
|
||||
ASN1_TYPE *ret = generate_v3(str, cnf, 0, &err);
|
||||
if (err)
|
||||
ASN1err(ASN1_F_ASN1_GENERATE_V3, err);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ASN1_TYPE *generate_v3(const char *str, X509V3_CTX *cnf, int depth,
|
||||
int *perr)
|
||||
{
|
||||
ASN1_TYPE *ret;
|
||||
tag_exp_arg asn1_tags;
|
||||
tag_exp_type *etmp;
|
||||
|
||||
int i, len;
|
||||
|
||||
unsigned char *orig_der = NULL, *new_der = NULL;
|
||||
const unsigned char *cpy_start;
|
||||
unsigned char *p;
|
||||
const unsigned char *cp;
|
||||
int cpy_len;
|
||||
long hdr_len = 0;
|
||||
int hdr_constructed = 0, hdr_tag, hdr_class;
|
||||
int r;
|
||||
|
||||
asn1_tags.imp_tag = -1;
|
||||
asn1_tags.imp_class = -1;
|
||||
asn1_tags.format = ASN1_GEN_FORMAT_ASCII;
|
||||
asn1_tags.exp_count = 0;
|
||||
if (CONF_parse_list(str, ',', 1, asn1_cb, &asn1_tags) != 0) {
|
||||
*perr = ASN1_R_UNKNOWN_TAG;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ((asn1_tags.utype == V_ASN1_SEQUENCE)
|
||||
|| (asn1_tags.utype == V_ASN1_SET)) {
|
||||
if (!cnf) {
|
||||
*perr = ASN1_R_SEQUENCE_OR_SET_NEEDS_CONFIG;
|
||||
return NULL;
|
||||
}
|
||||
if (depth >= ASN1_GEN_SEQ_MAX_DEPTH) {
|
||||
*perr = ASN1_R_ILLEGAL_NESTED_TAGGING;
|
||||
return NULL;
|
||||
}
|
||||
ret = asn1_multi(asn1_tags.utype, asn1_tags.str, cnf, depth, perr);
|
||||
} else
|
||||
ret = asn1_str2type(asn1_tags.str, asn1_tags.format, asn1_tags.utype);
|
||||
|
||||
if (!ret)
|
||||
return NULL;
|
||||
|
||||
/* If no tagging return base type */
|
||||
if ((asn1_tags.imp_tag == -1) && (asn1_tags.exp_count == 0))
|
||||
return ret;
|
||||
|
||||
/* Generate the encoding */
|
||||
cpy_len = i2d_ASN1_TYPE(ret, &orig_der);
|
||||
ASN1_TYPE_free(ret);
|
||||
ret = NULL;
|
||||
/* Set point to start copying for modified encoding */
|
||||
cpy_start = orig_der;
|
||||
|
||||
/* Do we need IMPLICIT tagging? */
|
||||
if (asn1_tags.imp_tag != -1) {
|
||||
/* If IMPLICIT we will replace the underlying tag */
|
||||
/* Skip existing tag+len */
|
||||
r = ASN1_get_object(&cpy_start, &hdr_len, &hdr_tag, &hdr_class,
|
||||
cpy_len);
|
||||
if (r & 0x80)
|
||||
goto err;
|
||||
/* Update copy length */
|
||||
cpy_len -= cpy_start - orig_der;
|
||||
/*
|
||||
* For IMPLICIT tagging the length should match the original length
|
||||
* and constructed flag should be consistent.
|
||||
*/
|
||||
if (r & 0x1) {
|
||||
/* Indefinite length constructed */
|
||||
hdr_constructed = 2;
|
||||
hdr_len = 0;
|
||||
} else
|
||||
/* Just retain constructed flag */
|
||||
hdr_constructed = r & V_ASN1_CONSTRUCTED;
|
||||
/*
|
||||
* Work out new length with IMPLICIT tag: ignore constructed because
|
||||
* it will mess up if indefinite length
|
||||
*/
|
||||
len = ASN1_object_size(0, hdr_len, asn1_tags.imp_tag);
|
||||
} else
|
||||
len = cpy_len;
|
||||
|
||||
/* Work out length in any EXPLICIT, starting from end */
|
||||
|
||||
for (i = 0, etmp = asn1_tags.exp_list + asn1_tags.exp_count - 1;
|
||||
i < asn1_tags.exp_count; i++, etmp--) {
|
||||
/* Content length: number of content octets + any padding */
|
||||
len += etmp->exp_pad;
|
||||
etmp->exp_len = len;
|
||||
/* Total object length: length including new header */
|
||||
len = ASN1_object_size(0, len, etmp->exp_tag);
|
||||
}
|
||||
|
||||
/* Allocate buffer for new encoding */
|
||||
|
||||
new_der = OPENSSL_malloc(len);
|
||||
if (new_der == NULL)
|
||||
goto err;
|
||||
|
||||
/* Generate tagged encoding */
|
||||
|
||||
p = new_der;
|
||||
|
||||
/* Output explicit tags first */
|
||||
|
||||
for (i = 0, etmp = asn1_tags.exp_list; i < asn1_tags.exp_count;
|
||||
i++, etmp++) {
|
||||
ASN1_put_object(&p, etmp->exp_constructed, etmp->exp_len,
|
||||
etmp->exp_tag, etmp->exp_class);
|
||||
if (etmp->exp_pad)
|
||||
*p++ = 0;
|
||||
}
|
||||
|
||||
/* If IMPLICIT, output tag */
|
||||
|
||||
if (asn1_tags.imp_tag != -1) {
|
||||
if (asn1_tags.imp_class == V_ASN1_UNIVERSAL
|
||||
&& (asn1_tags.imp_tag == V_ASN1_SEQUENCE
|
||||
|| asn1_tags.imp_tag == V_ASN1_SET))
|
||||
hdr_constructed = V_ASN1_CONSTRUCTED;
|
||||
ASN1_put_object(&p, hdr_constructed, hdr_len,
|
||||
asn1_tags.imp_tag, asn1_tags.imp_class);
|
||||
}
|
||||
|
||||
/* Copy across original encoding */
|
||||
memcpy(p, cpy_start, cpy_len);
|
||||
|
||||
cp = new_der;
|
||||
|
||||
/* Obtain new ASN1_TYPE structure */
|
||||
ret = d2i_ASN1_TYPE(NULL, &cp, len);
|
||||
|
||||
err:
|
||||
OPENSSL_free(orig_der);
|
||||
OPENSSL_free(new_der);
|
||||
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
static int asn1_cb(const char *elem, int len, void *bitstr)
|
||||
{
|
||||
tag_exp_arg *arg = bitstr;
|
||||
int i;
|
||||
int utype;
|
||||
int vlen = 0;
|
||||
const char *p, *vstart = NULL;
|
||||
|
||||
int tmp_tag, tmp_class;
|
||||
|
||||
if (elem == NULL)
|
||||
return -1;
|
||||
|
||||
for (i = 0, p = elem; i < len; p++, i++) {
|
||||
/* Look for the ':' in name value pairs */
|
||||
if (*p == ':') {
|
||||
vstart = p + 1;
|
||||
vlen = len - (vstart - elem);
|
||||
len = p - elem;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
utype = asn1_str2tag(elem, len);
|
||||
|
||||
if (utype == -1) {
|
||||
ASN1err(ASN1_F_ASN1_CB, ASN1_R_UNKNOWN_TAG);
|
||||
ERR_add_error_data(2, "tag=", elem);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* If this is not a modifier mark end of string and exit */
|
||||
if (!(utype & ASN1_GEN_FLAG)) {
|
||||
arg->utype = utype;
|
||||
arg->str = vstart;
|
||||
/* If no value and not end of string, error */
|
||||
if (!vstart && elem[len]) {
|
||||
ASN1err(ASN1_F_ASN1_CB, ASN1_R_MISSING_VALUE);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch (utype) {
|
||||
|
||||
case ASN1_GEN_FLAG_IMP:
|
||||
/* Check for illegal multiple IMPLICIT tagging */
|
||||
if (arg->imp_tag != -1) {
|
||||
ASN1err(ASN1_F_ASN1_CB, ASN1_R_ILLEGAL_NESTED_TAGGING);
|
||||
return -1;
|
||||
}
|
||||
if (!parse_tagging(vstart, vlen, &arg->imp_tag, &arg->imp_class))
|
||||
return -1;
|
||||
break;
|
||||
|
||||
case ASN1_GEN_FLAG_EXP:
|
||||
|
||||
if (!parse_tagging(vstart, vlen, &tmp_tag, &tmp_class))
|
||||
return -1;
|
||||
if (!append_exp(arg, tmp_tag, tmp_class, 1, 0, 0))
|
||||
return -1;
|
||||
break;
|
||||
|
||||
case ASN1_GEN_FLAG_SEQWRAP:
|
||||
if (!append_exp(arg, V_ASN1_SEQUENCE, V_ASN1_UNIVERSAL, 1, 0, 1))
|
||||
return -1;
|
||||
break;
|
||||
|
||||
case ASN1_GEN_FLAG_SETWRAP:
|
||||
if (!append_exp(arg, V_ASN1_SET, V_ASN1_UNIVERSAL, 1, 0, 1))
|
||||
return -1;
|
||||
break;
|
||||
|
||||
case ASN1_GEN_FLAG_BITWRAP:
|
||||
if (!append_exp(arg, V_ASN1_BIT_STRING, V_ASN1_UNIVERSAL, 0, 1, 1))
|
||||
return -1;
|
||||
break;
|
||||
|
||||
case ASN1_GEN_FLAG_OCTWRAP:
|
||||
if (!append_exp(arg, V_ASN1_OCTET_STRING, V_ASN1_UNIVERSAL, 0, 0, 1))
|
||||
return -1;
|
||||
break;
|
||||
|
||||
case ASN1_GEN_FLAG_FORMAT:
|
||||
if (!vstart) {
|
||||
ASN1err(ASN1_F_ASN1_CB, ASN1_R_UNKNOWN_FORMAT);
|
||||
return -1;
|
||||
}
|
||||
if (strncmp(vstart, "ASCII", 5) == 0)
|
||||
arg->format = ASN1_GEN_FORMAT_ASCII;
|
||||
else if (strncmp(vstart, "UTF8", 4) == 0)
|
||||
arg->format = ASN1_GEN_FORMAT_UTF8;
|
||||
else if (strncmp(vstart, "HEX", 3) == 0)
|
||||
arg->format = ASN1_GEN_FORMAT_HEX;
|
||||
else if (strncmp(vstart, "BITLIST", 7) == 0)
|
||||
arg->format = ASN1_GEN_FORMAT_BITLIST;
|
||||
else {
|
||||
ASN1err(ASN1_F_ASN1_CB, ASN1_R_UNKNOWN_FORMAT);
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
||||
}
|
||||
|
||||
static int parse_tagging(const char *vstart, int vlen, int *ptag, int *pclass)
|
||||
{
|
||||
char erch[2];
|
||||
long tag_num;
|
||||
char *eptr;
|
||||
if (!vstart)
|
||||
return 0;
|
||||
tag_num = strtoul(vstart, &eptr, 10);
|
||||
/* Check we haven't gone past max length: should be impossible */
|
||||
if (eptr && *eptr && (eptr > vstart + vlen))
|
||||
return 0;
|
||||
if (tag_num < 0) {
|
||||
ASN1err(ASN1_F_PARSE_TAGGING, ASN1_R_INVALID_NUMBER);
|
||||
return 0;
|
||||
}
|
||||
*ptag = tag_num;
|
||||
/* If we have non numeric characters, parse them */
|
||||
if (eptr)
|
||||
vlen -= eptr - vstart;
|
||||
else
|
||||
vlen = 0;
|
||||
if (vlen) {
|
||||
switch (*eptr) {
|
||||
|
||||
case 'U':
|
||||
*pclass = V_ASN1_UNIVERSAL;
|
||||
break;
|
||||
|
||||
case 'A':
|
||||
*pclass = V_ASN1_APPLICATION;
|
||||
break;
|
||||
|
||||
case 'P':
|
||||
*pclass = V_ASN1_PRIVATE;
|
||||
break;
|
||||
|
||||
case 'C':
|
||||
*pclass = V_ASN1_CONTEXT_SPECIFIC;
|
||||
break;
|
||||
|
||||
default:
|
||||
erch[0] = *eptr;
|
||||
erch[1] = 0;
|
||||
ASN1err(ASN1_F_PARSE_TAGGING, ASN1_R_INVALID_MODIFIER);
|
||||
ERR_add_error_data(2, "Char=", erch);
|
||||
return 0;
|
||||
|
||||
}
|
||||
} else
|
||||
*pclass = V_ASN1_CONTEXT_SPECIFIC;
|
||||
|
||||
return 1;
|
||||
|
||||
}
|
||||
|
||||
/* Handle multiple types: SET and SEQUENCE */
|
||||
|
||||
static ASN1_TYPE *asn1_multi(int utype, const char *section, X509V3_CTX *cnf,
|
||||
int depth, int *perr)
|
||||
{
|
||||
ASN1_TYPE *ret = NULL;
|
||||
STACK_OF(ASN1_TYPE) *sk = NULL;
|
||||
STACK_OF(CONF_VALUE) *sect = NULL;
|
||||
unsigned char *der = NULL;
|
||||
int derlen;
|
||||
int i;
|
||||
sk = sk_ASN1_TYPE_new_null();
|
||||
if (!sk)
|
||||
goto bad;
|
||||
if (section) {
|
||||
if (!cnf)
|
||||
goto bad;
|
||||
sect = X509V3_get_section(cnf, (char *)section);
|
||||
if (!sect)
|
||||
goto bad;
|
||||
for (i = 0; i < sk_CONF_VALUE_num(sect); i++) {
|
||||
ASN1_TYPE *typ =
|
||||
generate_v3(sk_CONF_VALUE_value(sect, i)->value, cnf,
|
||||
depth + 1, perr);
|
||||
if (!typ)
|
||||
goto bad;
|
||||
if (!sk_ASN1_TYPE_push(sk, typ))
|
||||
goto bad;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Now we has a STACK of the components, convert to the correct form
|
||||
*/
|
||||
|
||||
if (utype == V_ASN1_SET)
|
||||
derlen = i2d_ASN1_SET_ANY(sk, &der);
|
||||
else
|
||||
derlen = i2d_ASN1_SEQUENCE_ANY(sk, &der);
|
||||
|
||||
if (derlen < 0)
|
||||
goto bad;
|
||||
if ((ret = ASN1_TYPE_new()) == NULL)
|
||||
goto bad;
|
||||
if ((ret->value.asn1_string = ASN1_STRING_type_new(utype)) == NULL)
|
||||
goto bad;
|
||||
|
||||
ret->type = utype;
|
||||
ret->value.asn1_string->data = der;
|
||||
ret->value.asn1_string->length = derlen;
|
||||
|
||||
der = NULL;
|
||||
|
||||
bad:
|
||||
|
||||
OPENSSL_free(der);
|
||||
|
||||
sk_ASN1_TYPE_pop_free(sk, ASN1_TYPE_free);
|
||||
X509V3_section_free(cnf, sect);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int append_exp(tag_exp_arg *arg, int exp_tag, int exp_class,
|
||||
int exp_constructed, int exp_pad, int imp_ok)
|
||||
{
|
||||
tag_exp_type *exp_tmp;
|
||||
/* Can only have IMPLICIT if permitted */
|
||||
if ((arg->imp_tag != -1) && !imp_ok) {
|
||||
ASN1err(ASN1_F_APPEND_EXP, ASN1_R_ILLEGAL_IMPLICIT_TAG);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (arg->exp_count == ASN1_FLAG_EXP_MAX) {
|
||||
ASN1err(ASN1_F_APPEND_EXP, ASN1_R_DEPTH_EXCEEDED);
|
||||
return 0;
|
||||
}
|
||||
|
||||
exp_tmp = &arg->exp_list[arg->exp_count++];
|
||||
|
||||
/*
|
||||
* If IMPLICIT set tag to implicit value then reset implicit tag since it
|
||||
* has been used.
|
||||
*/
|
||||
if (arg->imp_tag != -1) {
|
||||
exp_tmp->exp_tag = arg->imp_tag;
|
||||
exp_tmp->exp_class = arg->imp_class;
|
||||
arg->imp_tag = -1;
|
||||
arg->imp_class = -1;
|
||||
} else {
|
||||
exp_tmp->exp_tag = exp_tag;
|
||||
exp_tmp->exp_class = exp_class;
|
||||
}
|
||||
exp_tmp->exp_constructed = exp_constructed;
|
||||
exp_tmp->exp_pad = exp_pad;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int asn1_str2tag(const char *tagstr, int len)
|
||||
{
|
||||
unsigned int i;
|
||||
static const struct tag_name_st *tntmp, tnst[] = {
|
||||
ASN1_GEN_STR("BOOL", V_ASN1_BOOLEAN),
|
||||
ASN1_GEN_STR("BOOLEAN", V_ASN1_BOOLEAN),
|
||||
ASN1_GEN_STR("NULL", V_ASN1_NULL),
|
||||
ASN1_GEN_STR("INT", V_ASN1_INTEGER),
|
||||
ASN1_GEN_STR("INTEGER", V_ASN1_INTEGER),
|
||||
ASN1_GEN_STR("ENUM", V_ASN1_ENUMERATED),
|
||||
ASN1_GEN_STR("ENUMERATED", V_ASN1_ENUMERATED),
|
||||
ASN1_GEN_STR("OID", V_ASN1_OBJECT),
|
||||
ASN1_GEN_STR("OBJECT", V_ASN1_OBJECT),
|
||||
ASN1_GEN_STR("UTCTIME", V_ASN1_UTCTIME),
|
||||
ASN1_GEN_STR("UTC", V_ASN1_UTCTIME),
|
||||
ASN1_GEN_STR("GENERALIZEDTIME", V_ASN1_GENERALIZEDTIME),
|
||||
ASN1_GEN_STR("GENTIME", V_ASN1_GENERALIZEDTIME),
|
||||
ASN1_GEN_STR("OCT", V_ASN1_OCTET_STRING),
|
||||
ASN1_GEN_STR("OCTETSTRING", V_ASN1_OCTET_STRING),
|
||||
ASN1_GEN_STR("BITSTR", V_ASN1_BIT_STRING),
|
||||
ASN1_GEN_STR("BITSTRING", V_ASN1_BIT_STRING),
|
||||
ASN1_GEN_STR("UNIVERSALSTRING", V_ASN1_UNIVERSALSTRING),
|
||||
ASN1_GEN_STR("UNIV", V_ASN1_UNIVERSALSTRING),
|
||||
ASN1_GEN_STR("IA5", V_ASN1_IA5STRING),
|
||||
ASN1_GEN_STR("IA5STRING", V_ASN1_IA5STRING),
|
||||
ASN1_GEN_STR("UTF8", V_ASN1_UTF8STRING),
|
||||
ASN1_GEN_STR("UTF8String", V_ASN1_UTF8STRING),
|
||||
ASN1_GEN_STR("BMP", V_ASN1_BMPSTRING),
|
||||
ASN1_GEN_STR("BMPSTRING", V_ASN1_BMPSTRING),
|
||||
ASN1_GEN_STR("VISIBLESTRING", V_ASN1_VISIBLESTRING),
|
||||
ASN1_GEN_STR("VISIBLE", V_ASN1_VISIBLESTRING),
|
||||
ASN1_GEN_STR("PRINTABLESTRING", V_ASN1_PRINTABLESTRING),
|
||||
ASN1_GEN_STR("PRINTABLE", V_ASN1_PRINTABLESTRING),
|
||||
ASN1_GEN_STR("T61", V_ASN1_T61STRING),
|
||||
ASN1_GEN_STR("T61STRING", V_ASN1_T61STRING),
|
||||
ASN1_GEN_STR("TELETEXSTRING", V_ASN1_T61STRING),
|
||||
ASN1_GEN_STR("GeneralString", V_ASN1_GENERALSTRING),
|
||||
ASN1_GEN_STR("GENSTR", V_ASN1_GENERALSTRING),
|
||||
ASN1_GEN_STR("NUMERIC", V_ASN1_NUMERICSTRING),
|
||||
ASN1_GEN_STR("NUMERICSTRING", V_ASN1_NUMERICSTRING),
|
||||
|
||||
/* Special cases */
|
||||
ASN1_GEN_STR("SEQUENCE", V_ASN1_SEQUENCE),
|
||||
ASN1_GEN_STR("SEQ", V_ASN1_SEQUENCE),
|
||||
ASN1_GEN_STR("SET", V_ASN1_SET),
|
||||
/* type modifiers */
|
||||
/* Explicit tag */
|
||||
ASN1_GEN_STR("EXP", ASN1_GEN_FLAG_EXP),
|
||||
ASN1_GEN_STR("EXPLICIT", ASN1_GEN_FLAG_EXP),
|
||||
/* Implicit tag */
|
||||
ASN1_GEN_STR("IMP", ASN1_GEN_FLAG_IMP),
|
||||
ASN1_GEN_STR("IMPLICIT", ASN1_GEN_FLAG_IMP),
|
||||
/* OCTET STRING wrapper */
|
||||
ASN1_GEN_STR("OCTWRAP", ASN1_GEN_FLAG_OCTWRAP),
|
||||
/* SEQUENCE wrapper */
|
||||
ASN1_GEN_STR("SEQWRAP", ASN1_GEN_FLAG_SEQWRAP),
|
||||
/* SET wrapper */
|
||||
ASN1_GEN_STR("SETWRAP", ASN1_GEN_FLAG_SETWRAP),
|
||||
/* BIT STRING wrapper */
|
||||
ASN1_GEN_STR("BITWRAP", ASN1_GEN_FLAG_BITWRAP),
|
||||
ASN1_GEN_STR("FORM", ASN1_GEN_FLAG_FORMAT),
|
||||
ASN1_GEN_STR("FORMAT", ASN1_GEN_FLAG_FORMAT),
|
||||
};
|
||||
|
||||
if (len == -1)
|
||||
len = strlen(tagstr);
|
||||
|
||||
tntmp = tnst;
|
||||
for (i = 0; i < OSSL_NELEM(tnst); i++, tntmp++) {
|
||||
if ((len == tntmp->len) && (strncmp(tntmp->strnam, tagstr, len) == 0))
|
||||
return tntmp->tag;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static ASN1_TYPE *asn1_str2type(const char *str, int format, int utype)
|
||||
{
|
||||
ASN1_TYPE *atmp = NULL;
|
||||
CONF_VALUE vtmp;
|
||||
unsigned char *rdata;
|
||||
long rdlen;
|
||||
int no_unused = 1;
|
||||
|
||||
if ((atmp = ASN1_TYPE_new()) == NULL) {
|
||||
ASN1err(ASN1_F_ASN1_STR2TYPE, ERR_R_MALLOC_FAILURE);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!str)
|
||||
str = "";
|
||||
|
||||
switch (utype) {
|
||||
|
||||
case V_ASN1_NULL:
|
||||
if (str && *str) {
|
||||
ASN1err(ASN1_F_ASN1_STR2TYPE, ASN1_R_ILLEGAL_NULL_VALUE);
|
||||
goto bad_form;
|
||||
}
|
||||
break;
|
||||
|
||||
case V_ASN1_BOOLEAN:
|
||||
if (format != ASN1_GEN_FORMAT_ASCII) {
|
||||
ASN1err(ASN1_F_ASN1_STR2TYPE, ASN1_R_NOT_ASCII_FORMAT);
|
||||
goto bad_form;
|
||||
}
|
||||
vtmp.name = NULL;
|
||||
vtmp.section = NULL;
|
||||
vtmp.value = (char *)str;
|
||||
if (!X509V3_get_value_bool(&vtmp, &atmp->value.boolean)) {
|
||||
ASN1err(ASN1_F_ASN1_STR2TYPE, ASN1_R_ILLEGAL_BOOLEAN);
|
||||
goto bad_str;
|
||||
}
|
||||
break;
|
||||
|
||||
case V_ASN1_INTEGER:
|
||||
case V_ASN1_ENUMERATED:
|
||||
if (format != ASN1_GEN_FORMAT_ASCII) {
|
||||
ASN1err(ASN1_F_ASN1_STR2TYPE, ASN1_R_INTEGER_NOT_ASCII_FORMAT);
|
||||
goto bad_form;
|
||||
}
|
||||
if ((atmp->value.integer
|
||||
= s2i_ASN1_INTEGER(NULL, str)) == NULL) {
|
||||
ASN1err(ASN1_F_ASN1_STR2TYPE, ASN1_R_ILLEGAL_INTEGER);
|
||||
goto bad_str;
|
||||
}
|
||||
break;
|
||||
|
||||
case V_ASN1_OBJECT:
|
||||
if (format != ASN1_GEN_FORMAT_ASCII) {
|
||||
ASN1err(ASN1_F_ASN1_STR2TYPE, ASN1_R_OBJECT_NOT_ASCII_FORMAT);
|
||||
goto bad_form;
|
||||
}
|
||||
if ((atmp->value.object = OBJ_txt2obj(str, 0)) == NULL) {
|
||||
ASN1err(ASN1_F_ASN1_STR2TYPE, ASN1_R_ILLEGAL_OBJECT);
|
||||
goto bad_str;
|
||||
}
|
||||
break;
|
||||
|
||||
case V_ASN1_UTCTIME:
|
||||
case V_ASN1_GENERALIZEDTIME:
|
||||
if (format != ASN1_GEN_FORMAT_ASCII) {
|
||||
ASN1err(ASN1_F_ASN1_STR2TYPE, ASN1_R_TIME_NOT_ASCII_FORMAT);
|
||||
goto bad_form;
|
||||
}
|
||||
if ((atmp->value.asn1_string = ASN1_STRING_new()) == NULL) {
|
||||
ASN1err(ASN1_F_ASN1_STR2TYPE, ERR_R_MALLOC_FAILURE);
|
||||
goto bad_str;
|
||||
}
|
||||
if (!ASN1_STRING_set(atmp->value.asn1_string, str, -1)) {
|
||||
ASN1err(ASN1_F_ASN1_STR2TYPE, ERR_R_MALLOC_FAILURE);
|
||||
goto bad_str;
|
||||
}
|
||||
atmp->value.asn1_string->type = utype;
|
||||
if (!ASN1_TIME_check(atmp->value.asn1_string)) {
|
||||
ASN1err(ASN1_F_ASN1_STR2TYPE, ASN1_R_ILLEGAL_TIME_VALUE);
|
||||
goto bad_str;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case V_ASN1_BMPSTRING:
|
||||
case V_ASN1_PRINTABLESTRING:
|
||||
case V_ASN1_IA5STRING:
|
||||
case V_ASN1_T61STRING:
|
||||
case V_ASN1_UTF8STRING:
|
||||
case V_ASN1_VISIBLESTRING:
|
||||
case V_ASN1_UNIVERSALSTRING:
|
||||
case V_ASN1_GENERALSTRING:
|
||||
case V_ASN1_NUMERICSTRING:
|
||||
if (format == ASN1_GEN_FORMAT_ASCII)
|
||||
format = MBSTRING_ASC;
|
||||
else if (format == ASN1_GEN_FORMAT_UTF8)
|
||||
format = MBSTRING_UTF8;
|
||||
else {
|
||||
ASN1err(ASN1_F_ASN1_STR2TYPE, ASN1_R_ILLEGAL_FORMAT);
|
||||
goto bad_form;
|
||||
}
|
||||
|
||||
if (ASN1_mbstring_copy(&atmp->value.asn1_string, (unsigned char *)str,
|
||||
-1, format, ASN1_tag2bit(utype)) <= 0) {
|
||||
ASN1err(ASN1_F_ASN1_STR2TYPE, ERR_R_MALLOC_FAILURE);
|
||||
goto bad_str;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case V_ASN1_BIT_STRING:
|
||||
case V_ASN1_OCTET_STRING:
|
||||
if ((atmp->value.asn1_string = ASN1_STRING_new()) == NULL) {
|
||||
ASN1err(ASN1_F_ASN1_STR2TYPE, ERR_R_MALLOC_FAILURE);
|
||||
goto bad_form;
|
||||
}
|
||||
|
||||
if (format == ASN1_GEN_FORMAT_HEX) {
|
||||
if ((rdata = OPENSSL_hexstr2buf(str, &rdlen)) == NULL) {
|
||||
ASN1err(ASN1_F_ASN1_STR2TYPE, ASN1_R_ILLEGAL_HEX);
|
||||
goto bad_str;
|
||||
}
|
||||
atmp->value.asn1_string->data = rdata;
|
||||
atmp->value.asn1_string->length = rdlen;
|
||||
atmp->value.asn1_string->type = utype;
|
||||
} else if (format == ASN1_GEN_FORMAT_ASCII)
|
||||
ASN1_STRING_set(atmp->value.asn1_string, str, -1);
|
||||
else if ((format == ASN1_GEN_FORMAT_BITLIST)
|
||||
&& (utype == V_ASN1_BIT_STRING)) {
|
||||
if (!CONF_parse_list
|
||||
(str, ',', 1, bitstr_cb, atmp->value.bit_string)) {
|
||||
ASN1err(ASN1_F_ASN1_STR2TYPE, ASN1_R_LIST_ERROR);
|
||||
goto bad_str;
|
||||
}
|
||||
no_unused = 0;
|
||||
|
||||
} else {
|
||||
ASN1err(ASN1_F_ASN1_STR2TYPE, ASN1_R_ILLEGAL_BITSTRING_FORMAT);
|
||||
goto bad_form;
|
||||
}
|
||||
|
||||
if ((utype == V_ASN1_BIT_STRING) && no_unused) {
|
||||
atmp->value.asn1_string->flags
|
||||
&= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07);
|
||||
atmp->value.asn1_string->flags |= ASN1_STRING_FLAG_BITS_LEFT;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
ASN1err(ASN1_F_ASN1_STR2TYPE, ASN1_R_UNSUPPORTED_TYPE);
|
||||
goto bad_str;
|
||||
}
|
||||
|
||||
atmp->type = utype;
|
||||
return atmp;
|
||||
|
||||
bad_str:
|
||||
ERR_add_error_data(2, "string=", str);
|
||||
bad_form:
|
||||
|
||||
ASN1_TYPE_free(atmp);
|
||||
return NULL;
|
||||
|
||||
}
|
||||
|
||||
static int bitstr_cb(const char *elem, int len, void *bitstr)
|
||||
{
|
||||
long bitnum;
|
||||
char *eptr;
|
||||
if (!elem)
|
||||
return 0;
|
||||
bitnum = strtoul(elem, &eptr, 10);
|
||||
if (eptr && *eptr && (eptr != elem + len))
|
||||
return 0;
|
||||
if (bitnum < 0) {
|
||||
ASN1err(ASN1_F_BITSTR_CB, ASN1_R_INVALID_NUMBER);
|
||||
return 0;
|
||||
}
|
||||
if (!ASN1_BIT_STRING_set_bit(bitstr, bitnum, 1)) {
|
||||
ASN1err(ASN1_F_BITSTR_CB, ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int mask_cb(const char *elem, int len, void *arg)
|
||||
{
|
||||
unsigned long *pmask = arg, tmpmask;
|
||||
int tag;
|
||||
if (elem == NULL)
|
||||
return 0;
|
||||
if ((len == 3) && (strncmp(elem, "DIR", 3) == 0)) {
|
||||
*pmask |= B_ASN1_DIRECTORYSTRING;
|
||||
return 1;
|
||||
}
|
||||
tag = asn1_str2tag(elem, len);
|
||||
if (!tag || (tag & ASN1_GEN_FLAG))
|
||||
return 0;
|
||||
tmpmask = ASN1_tag2bit(tag);
|
||||
if (!tmpmask)
|
||||
return 0;
|
||||
*pmask |= tmpmask;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ASN1_str2mask(const char *str, unsigned long *pmask)
|
||||
{
|
||||
*pmask = 0;
|
||||
return CONF_parse_list(str, '|', 1, mask_cb, pmask);
|
||||
}
|
||||
42
crypto/asn1/asn1_item_list.c
Normal file
42
crypto/asn1/asn1_item_list.c
Normal file
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "internal/cryptlib.h"
|
||||
#include <openssl/asn1.h>
|
||||
#include <openssl/asn1t.h>
|
||||
#include <openssl/cms.h>
|
||||
#include <openssl/dh.h>
|
||||
#include <openssl/ocsp.h>
|
||||
#include <openssl/pkcs7.h>
|
||||
#include <openssl/pkcs12.h>
|
||||
#include <openssl/rsa.h>
|
||||
#include <openssl/x509v3.h>
|
||||
|
||||
#include "asn1_item_list.h"
|
||||
|
||||
const ASN1_ITEM *ASN1_ITEM_lookup(const char *name)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < OSSL_NELEM(asn1_item_list); i++) {
|
||||
const ASN1_ITEM *it = ASN1_ITEM_ptr(asn1_item_list[i]);
|
||||
|
||||
if (strcmp(it->sname, name) == 0)
|
||||
return it;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const ASN1_ITEM *ASN1_ITEM_get(size_t i)
|
||||
{
|
||||
if (i >= OSSL_NELEM(asn1_item_list))
|
||||
return NULL;
|
||||
return ASN1_ITEM_ptr(asn1_item_list[i]);
|
||||
}
|
||||
178
crypto/asn1/asn1_item_list.h
Normal file
178
crypto/asn1/asn1_item_list.h
Normal file
@@ -0,0 +1,178 @@
|
||||
/*
|
||||
* Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
static ASN1_ITEM_EXP *asn1_item_list[] = {
|
||||
|
||||
ASN1_ITEM_ref(ACCESS_DESCRIPTION),
|
||||
#ifndef OPENSSL_NO_RFC3779
|
||||
ASN1_ITEM_ref(ASIdOrRange),
|
||||
ASN1_ITEM_ref(ASIdentifierChoice),
|
||||
ASN1_ITEM_ref(ASIdentifiers),
|
||||
#endif
|
||||
ASN1_ITEM_ref(ASN1_ANY),
|
||||
ASN1_ITEM_ref(ASN1_BIT_STRING),
|
||||
ASN1_ITEM_ref(ASN1_BMPSTRING),
|
||||
ASN1_ITEM_ref(ASN1_BOOLEAN),
|
||||
ASN1_ITEM_ref(ASN1_ENUMERATED),
|
||||
ASN1_ITEM_ref(ASN1_FBOOLEAN),
|
||||
ASN1_ITEM_ref(ASN1_GENERALIZEDTIME),
|
||||
ASN1_ITEM_ref(ASN1_GENERALSTRING),
|
||||
ASN1_ITEM_ref(ASN1_IA5STRING),
|
||||
ASN1_ITEM_ref(ASN1_INTEGER),
|
||||
ASN1_ITEM_ref(ASN1_NULL),
|
||||
ASN1_ITEM_ref(ASN1_OBJECT),
|
||||
ASN1_ITEM_ref(ASN1_OCTET_STRING_NDEF),
|
||||
ASN1_ITEM_ref(ASN1_OCTET_STRING),
|
||||
ASN1_ITEM_ref(ASN1_PRINTABLESTRING),
|
||||
ASN1_ITEM_ref(ASN1_PRINTABLE),
|
||||
ASN1_ITEM_ref(ASN1_SEQUENCE_ANY),
|
||||
ASN1_ITEM_ref(ASN1_SEQUENCE),
|
||||
ASN1_ITEM_ref(ASN1_SET_ANY),
|
||||
ASN1_ITEM_ref(ASN1_T61STRING),
|
||||
ASN1_ITEM_ref(ASN1_TBOOLEAN),
|
||||
ASN1_ITEM_ref(ASN1_TIME),
|
||||
ASN1_ITEM_ref(ASN1_UNIVERSALSTRING),
|
||||
ASN1_ITEM_ref(ASN1_UTCTIME),
|
||||
ASN1_ITEM_ref(ASN1_UTF8STRING),
|
||||
ASN1_ITEM_ref(ASN1_VISIBLESTRING),
|
||||
#ifndef OPENSSL_NO_RFC3779
|
||||
ASN1_ITEM_ref(ASRange),
|
||||
#endif
|
||||
ASN1_ITEM_ref(AUTHORITY_INFO_ACCESS),
|
||||
ASN1_ITEM_ref(AUTHORITY_KEYID),
|
||||
ASN1_ITEM_ref(BASIC_CONSTRAINTS),
|
||||
ASN1_ITEM_ref(BIGNUM),
|
||||
ASN1_ITEM_ref(CBIGNUM),
|
||||
ASN1_ITEM_ref(CERTIFICATEPOLICIES),
|
||||
#ifndef OPENSSL_NO_CMS
|
||||
ASN1_ITEM_ref(CMS_ContentInfo),
|
||||
ASN1_ITEM_ref(CMS_ReceiptRequest),
|
||||
#endif
|
||||
ASN1_ITEM_ref(CRL_DIST_POINTS),
|
||||
#ifndef OPENSSL_NO_DH
|
||||
ASN1_ITEM_ref(DHparams),
|
||||
#endif
|
||||
ASN1_ITEM_ref(DIRECTORYSTRING),
|
||||
ASN1_ITEM_ref(DISPLAYTEXT),
|
||||
ASN1_ITEM_ref(DIST_POINT_NAME),
|
||||
ASN1_ITEM_ref(DIST_POINT),
|
||||
#ifndef OPENSSL_NO_EC
|
||||
ASN1_ITEM_ref(ECPARAMETERS),
|
||||
ASN1_ITEM_ref(ECPKPARAMETERS),
|
||||
#endif
|
||||
ASN1_ITEM_ref(EDIPARTYNAME),
|
||||
ASN1_ITEM_ref(EXTENDED_KEY_USAGE),
|
||||
ASN1_ITEM_ref(GENERAL_NAMES),
|
||||
ASN1_ITEM_ref(GENERAL_NAME),
|
||||
ASN1_ITEM_ref(GENERAL_SUBTREE),
|
||||
#ifndef OPENSSL_NO_RFC3779
|
||||
ASN1_ITEM_ref(IPAddressChoice),
|
||||
ASN1_ITEM_ref(IPAddressFamily),
|
||||
ASN1_ITEM_ref(IPAddressOrRange),
|
||||
ASN1_ITEM_ref(IPAddressRange),
|
||||
#endif
|
||||
ASN1_ITEM_ref(ISSUING_DIST_POINT),
|
||||
#if OPENSSL_API_COMPAT < 0x10200000L
|
||||
ASN1_ITEM_ref(LONG),
|
||||
#endif
|
||||
ASN1_ITEM_ref(NAME_CONSTRAINTS),
|
||||
ASN1_ITEM_ref(NETSCAPE_CERT_SEQUENCE),
|
||||
ASN1_ITEM_ref(NETSCAPE_SPKAC),
|
||||
ASN1_ITEM_ref(NETSCAPE_SPKI),
|
||||
ASN1_ITEM_ref(NOTICEREF),
|
||||
#ifndef OPENSSL_NO_OCSP
|
||||
ASN1_ITEM_ref(OCSP_BASICRESP),
|
||||
ASN1_ITEM_ref(OCSP_CERTID),
|
||||
ASN1_ITEM_ref(OCSP_CERTSTATUS),
|
||||
ASN1_ITEM_ref(OCSP_CRLID),
|
||||
ASN1_ITEM_ref(OCSP_ONEREQ),
|
||||
ASN1_ITEM_ref(OCSP_REQINFO),
|
||||
ASN1_ITEM_ref(OCSP_REQUEST),
|
||||
ASN1_ITEM_ref(OCSP_RESPBYTES),
|
||||
ASN1_ITEM_ref(OCSP_RESPDATA),
|
||||
ASN1_ITEM_ref(OCSP_RESPID),
|
||||
ASN1_ITEM_ref(OCSP_RESPONSE),
|
||||
ASN1_ITEM_ref(OCSP_REVOKEDINFO),
|
||||
ASN1_ITEM_ref(OCSP_SERVICELOC),
|
||||
ASN1_ITEM_ref(OCSP_SIGNATURE),
|
||||
ASN1_ITEM_ref(OCSP_SINGLERESP),
|
||||
#endif
|
||||
ASN1_ITEM_ref(OTHERNAME),
|
||||
ASN1_ITEM_ref(PBE2PARAM),
|
||||
ASN1_ITEM_ref(PBEPARAM),
|
||||
ASN1_ITEM_ref(PBKDF2PARAM),
|
||||
ASN1_ITEM_ref(PKCS12_AUTHSAFES),
|
||||
ASN1_ITEM_ref(PKCS12_BAGS),
|
||||
ASN1_ITEM_ref(PKCS12_MAC_DATA),
|
||||
ASN1_ITEM_ref(PKCS12_SAFEBAGS),
|
||||
ASN1_ITEM_ref(PKCS12_SAFEBAG),
|
||||
ASN1_ITEM_ref(PKCS12),
|
||||
ASN1_ITEM_ref(PKCS7_ATTR_SIGN),
|
||||
ASN1_ITEM_ref(PKCS7_ATTR_VERIFY),
|
||||
ASN1_ITEM_ref(PKCS7_DIGEST),
|
||||
ASN1_ITEM_ref(PKCS7_ENCRYPT),
|
||||
ASN1_ITEM_ref(PKCS7_ENC_CONTENT),
|
||||
ASN1_ITEM_ref(PKCS7_ENVELOPE),
|
||||
ASN1_ITEM_ref(PKCS7_ISSUER_AND_SERIAL),
|
||||
ASN1_ITEM_ref(PKCS7_RECIP_INFO),
|
||||
ASN1_ITEM_ref(PKCS7_SIGNED),
|
||||
ASN1_ITEM_ref(PKCS7_SIGNER_INFO),
|
||||
ASN1_ITEM_ref(PKCS7_SIGN_ENVELOPE),
|
||||
ASN1_ITEM_ref(PKCS7),
|
||||
ASN1_ITEM_ref(PKCS8_PRIV_KEY_INFO),
|
||||
ASN1_ITEM_ref(PKEY_USAGE_PERIOD),
|
||||
ASN1_ITEM_ref(POLICYINFO),
|
||||
ASN1_ITEM_ref(POLICYQUALINFO),
|
||||
ASN1_ITEM_ref(POLICY_CONSTRAINTS),
|
||||
ASN1_ITEM_ref(POLICY_MAPPINGS),
|
||||
ASN1_ITEM_ref(POLICY_MAPPING),
|
||||
ASN1_ITEM_ref(PROXY_CERT_INFO_EXTENSION),
|
||||
ASN1_ITEM_ref(PROXY_POLICY),
|
||||
#ifndef OPENSSL_NO_RSA
|
||||
ASN1_ITEM_ref(RSAPrivateKey),
|
||||
ASN1_ITEM_ref(RSAPublicKey),
|
||||
ASN1_ITEM_ref(RSA_OAEP_PARAMS),
|
||||
ASN1_ITEM_ref(RSA_PSS_PARAMS),
|
||||
#endif
|
||||
#ifndef OPENSSL_NO_SCRYPT
|
||||
ASN1_ITEM_ref(SCRYPT_PARAMS),
|
||||
#endif
|
||||
ASN1_ITEM_ref(SXNETID),
|
||||
ASN1_ITEM_ref(SXNET),
|
||||
ASN1_ITEM_ref(USERNOTICE),
|
||||
ASN1_ITEM_ref(X509_ALGORS),
|
||||
ASN1_ITEM_ref(X509_ALGOR),
|
||||
ASN1_ITEM_ref(X509_ATTRIBUTE),
|
||||
ASN1_ITEM_ref(X509_CERT_AUX),
|
||||
ASN1_ITEM_ref(X509_CINF),
|
||||
ASN1_ITEM_ref(X509_CRL_INFO),
|
||||
ASN1_ITEM_ref(X509_CRL),
|
||||
ASN1_ITEM_ref(X509_EXTENSIONS),
|
||||
ASN1_ITEM_ref(X509_EXTENSION),
|
||||
ASN1_ITEM_ref(X509_NAME_ENTRY),
|
||||
ASN1_ITEM_ref(X509_NAME),
|
||||
ASN1_ITEM_ref(X509_PUBKEY),
|
||||
ASN1_ITEM_ref(X509_REQ_INFO),
|
||||
ASN1_ITEM_ref(X509_REQ),
|
||||
ASN1_ITEM_ref(X509_REVOKED),
|
||||
ASN1_ITEM_ref(X509_SIG),
|
||||
ASN1_ITEM_ref(X509_VAL),
|
||||
ASN1_ITEM_ref(X509),
|
||||
#if OPENSSL_API_COMPAT < 0x10200000L
|
||||
ASN1_ITEM_ref(ZLONG),
|
||||
#endif
|
||||
ASN1_ITEM_ref(INT32),
|
||||
ASN1_ITEM_ref(UINT32),
|
||||
ASN1_ITEM_ref(ZINT32),
|
||||
ASN1_ITEM_ref(ZUINT32),
|
||||
ASN1_ITEM_ref(INT64),
|
||||
ASN1_ITEM_ref(UINT64),
|
||||
ASN1_ITEM_ref(ZINT64),
|
||||
ASN1_ITEM_ref(ZUINT64),
|
||||
};
|
||||
391
crypto/asn1/asn1_lib.c
Normal file
391
crypto/asn1/asn1_lib.c
Normal file
@@ -0,0 +1,391 @@
|
||||
/*
|
||||
* Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <limits.h>
|
||||
#include "internal/cryptlib.h"
|
||||
#include <openssl/asn1.h>
|
||||
#include "asn1_locl.h"
|
||||
|
||||
static int asn1_get_length(const unsigned char **pp, int *inf, long *rl,
|
||||
long max);
|
||||
static void asn1_put_length(unsigned char **pp, int length);
|
||||
|
||||
static int _asn1_check_infinite_end(const unsigned char **p, long len)
|
||||
{
|
||||
/*
|
||||
* If there is 0 or 1 byte left, the length check should pick things up
|
||||
*/
|
||||
if (len <= 0)
|
||||
return 1;
|
||||
else if ((len >= 2) && ((*p)[0] == 0) && ((*p)[1] == 0)) {
|
||||
(*p) += 2;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ASN1_check_infinite_end(unsigned char **p, long len)
|
||||
{
|
||||
return _asn1_check_infinite_end((const unsigned char **)p, len);
|
||||
}
|
||||
|
||||
int ASN1_const_check_infinite_end(const unsigned char **p, long len)
|
||||
{
|
||||
return _asn1_check_infinite_end(p, len);
|
||||
}
|
||||
|
||||
int ASN1_get_object(const unsigned char **pp, long *plength, int *ptag,
|
||||
int *pclass, long omax)
|
||||
{
|
||||
int i, ret;
|
||||
long l;
|
||||
const unsigned char *p = *pp;
|
||||
int tag, xclass, inf;
|
||||
long max = omax;
|
||||
|
||||
if (!max)
|
||||
goto err;
|
||||
ret = (*p & V_ASN1_CONSTRUCTED);
|
||||
xclass = (*p & V_ASN1_PRIVATE);
|
||||
i = *p & V_ASN1_PRIMITIVE_TAG;
|
||||
if (i == V_ASN1_PRIMITIVE_TAG) { /* high-tag */
|
||||
p++;
|
||||
if (--max == 0)
|
||||
goto err;
|
||||
l = 0;
|
||||
while (*p & 0x80) {
|
||||
l <<= 7L;
|
||||
l |= *(p++) & 0x7f;
|
||||
if (--max == 0)
|
||||
goto err;
|
||||
if (l > (INT_MAX >> 7L))
|
||||
goto err;
|
||||
}
|
||||
l <<= 7L;
|
||||
l |= *(p++) & 0x7f;
|
||||
tag = (int)l;
|
||||
if (--max == 0)
|
||||
goto err;
|
||||
} else {
|
||||
tag = i;
|
||||
p++;
|
||||
if (--max == 0)
|
||||
goto err;
|
||||
}
|
||||
*ptag = tag;
|
||||
*pclass = xclass;
|
||||
if (!asn1_get_length(&p, &inf, plength, max))
|
||||
goto err;
|
||||
|
||||
if (inf && !(ret & V_ASN1_CONSTRUCTED))
|
||||
goto err;
|
||||
|
||||
if (*plength > (omax - (p - *pp))) {
|
||||
ASN1err(ASN1_F_ASN1_GET_OBJECT, ASN1_R_TOO_LONG);
|
||||
/*
|
||||
* Set this so that even if things are not long enough the values are
|
||||
* set correctly
|
||||
*/
|
||||
ret |= 0x80;
|
||||
}
|
||||
*pp = p;
|
||||
return ret | inf;
|
||||
err:
|
||||
ASN1err(ASN1_F_ASN1_GET_OBJECT, ASN1_R_HEADER_TOO_LONG);
|
||||
return 0x80;
|
||||
}
|
||||
|
||||
/*
|
||||
* Decode a length field.
|
||||
* The short form is a single byte defining a length 0 - 127.
|
||||
* The long form is a byte 0 - 127 with the top bit set and this indicates
|
||||
* the number of following octets that contain the length. These octets
|
||||
* are stored most significant digit first.
|
||||
*/
|
||||
static int asn1_get_length(const unsigned char **pp, int *inf, long *rl,
|
||||
long max)
|
||||
{
|
||||
const unsigned char *p = *pp;
|
||||
unsigned long ret = 0;
|
||||
int i;
|
||||
|
||||
if (max-- < 1)
|
||||
return 0;
|
||||
if (*p == 0x80) {
|
||||
*inf = 1;
|
||||
p++;
|
||||
} else {
|
||||
*inf = 0;
|
||||
i = *p & 0x7f;
|
||||
if (*p++ & 0x80) {
|
||||
if (max < i + 1)
|
||||
return 0;
|
||||
/* Skip leading zeroes */
|
||||
while (i > 0 && *p == 0) {
|
||||
p++;
|
||||
i--;
|
||||
}
|
||||
if (i > (int)sizeof(long))
|
||||
return 0;
|
||||
while (i > 0) {
|
||||
ret <<= 8;
|
||||
ret |= *p++;
|
||||
i--;
|
||||
}
|
||||
if (ret > LONG_MAX)
|
||||
return 0;
|
||||
} else
|
||||
ret = i;
|
||||
}
|
||||
*pp = p;
|
||||
*rl = (long)ret;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* class 0 is constructed constructed == 2 for indefinite length constructed
|
||||
*/
|
||||
void ASN1_put_object(unsigned char **pp, int constructed, int length, int tag,
|
||||
int xclass)
|
||||
{
|
||||
unsigned char *p = *pp;
|
||||
int i, ttag;
|
||||
|
||||
i = (constructed) ? V_ASN1_CONSTRUCTED : 0;
|
||||
i |= (xclass & V_ASN1_PRIVATE);
|
||||
if (tag < 31)
|
||||
*(p++) = i | (tag & V_ASN1_PRIMITIVE_TAG);
|
||||
else {
|
||||
*(p++) = i | V_ASN1_PRIMITIVE_TAG;
|
||||
for (i = 0, ttag = tag; ttag > 0; i++)
|
||||
ttag >>= 7;
|
||||
ttag = i;
|
||||
while (i-- > 0) {
|
||||
p[i] = tag & 0x7f;
|
||||
if (i != (ttag - 1))
|
||||
p[i] |= 0x80;
|
||||
tag >>= 7;
|
||||
}
|
||||
p += ttag;
|
||||
}
|
||||
if (constructed == 2)
|
||||
*(p++) = 0x80;
|
||||
else
|
||||
asn1_put_length(&p, length);
|
||||
*pp = p;
|
||||
}
|
||||
|
||||
int ASN1_put_eoc(unsigned char **pp)
|
||||
{
|
||||
unsigned char *p = *pp;
|
||||
*p++ = 0;
|
||||
*p++ = 0;
|
||||
*pp = p;
|
||||
return 2;
|
||||
}
|
||||
|
||||
static void asn1_put_length(unsigned char **pp, int length)
|
||||
{
|
||||
unsigned char *p = *pp;
|
||||
int i, l;
|
||||
if (length <= 127)
|
||||
*(p++) = (unsigned char)length;
|
||||
else {
|
||||
l = length;
|
||||
for (i = 0; l > 0; i++)
|
||||
l >>= 8;
|
||||
*(p++) = i | 0x80;
|
||||
l = i;
|
||||
while (i-- > 0) {
|
||||
p[i] = length & 0xff;
|
||||
length >>= 8;
|
||||
}
|
||||
p += l;
|
||||
}
|
||||
*pp = p;
|
||||
}
|
||||
|
||||
int ASN1_object_size(int constructed, int length, int tag)
|
||||
{
|
||||
int ret = 1;
|
||||
if (length < 0)
|
||||
return -1;
|
||||
if (tag >= 31) {
|
||||
while (tag > 0) {
|
||||
tag >>= 7;
|
||||
ret++;
|
||||
}
|
||||
}
|
||||
if (constructed == 2) {
|
||||
ret += 3;
|
||||
} else {
|
||||
ret++;
|
||||
if (length > 127) {
|
||||
int tmplen = length;
|
||||
while (tmplen > 0) {
|
||||
tmplen >>= 8;
|
||||
ret++;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ret >= INT_MAX - length)
|
||||
return -1;
|
||||
return ret + length;
|
||||
}
|
||||
|
||||
int ASN1_STRING_copy(ASN1_STRING *dst, const ASN1_STRING *str)
|
||||
{
|
||||
if (str == NULL)
|
||||
return 0;
|
||||
dst->type = str->type;
|
||||
if (!ASN1_STRING_set(dst, str->data, str->length))
|
||||
return 0;
|
||||
/* Copy flags but preserve embed value */
|
||||
dst->flags &= ASN1_STRING_FLAG_EMBED;
|
||||
dst->flags |= str->flags & ~ASN1_STRING_FLAG_EMBED;
|
||||
return 1;
|
||||
}
|
||||
|
||||
ASN1_STRING *ASN1_STRING_dup(const ASN1_STRING *str)
|
||||
{
|
||||
ASN1_STRING *ret;
|
||||
if (!str)
|
||||
return NULL;
|
||||
ret = ASN1_STRING_new();
|
||||
if (ret == NULL)
|
||||
return NULL;
|
||||
if (!ASN1_STRING_copy(ret, str)) {
|
||||
ASN1_STRING_free(ret);
|
||||
return NULL;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ASN1_STRING_set(ASN1_STRING *str, const void *_data, int len)
|
||||
{
|
||||
unsigned char *c;
|
||||
const char *data = _data;
|
||||
|
||||
if (len < 0) {
|
||||
if (data == NULL)
|
||||
return 0;
|
||||
else
|
||||
len = strlen(data);
|
||||
}
|
||||
if ((str->length <= len) || (str->data == NULL)) {
|
||||
c = str->data;
|
||||
str->data = OPENSSL_realloc(c, len + 1);
|
||||
if (str->data == NULL) {
|
||||
ASN1err(ASN1_F_ASN1_STRING_SET, ERR_R_MALLOC_FAILURE);
|
||||
str->data = c;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
str->length = len;
|
||||
if (data != NULL) {
|
||||
memcpy(str->data, data, len);
|
||||
/* an allowance for strings :-) */
|
||||
str->data[len] = '\0';
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
void ASN1_STRING_set0(ASN1_STRING *str, void *data, int len)
|
||||
{
|
||||
OPENSSL_free(str->data);
|
||||
str->data = data;
|
||||
str->length = len;
|
||||
}
|
||||
|
||||
ASN1_STRING *ASN1_STRING_new(void)
|
||||
{
|
||||
return ASN1_STRING_type_new(V_ASN1_OCTET_STRING);
|
||||
}
|
||||
|
||||
ASN1_STRING *ASN1_STRING_type_new(int type)
|
||||
{
|
||||
ASN1_STRING *ret;
|
||||
|
||||
ret = OPENSSL_zalloc(sizeof(*ret));
|
||||
if (ret == NULL) {
|
||||
ASN1err(ASN1_F_ASN1_STRING_TYPE_NEW, ERR_R_MALLOC_FAILURE);
|
||||
return NULL;
|
||||
}
|
||||
ret->type = type;
|
||||
return ret;
|
||||
}
|
||||
|
||||
void asn1_string_embed_free(ASN1_STRING *a, int embed)
|
||||
{
|
||||
if (a == NULL)
|
||||
return;
|
||||
if (!(a->flags & ASN1_STRING_FLAG_NDEF))
|
||||
OPENSSL_free(a->data);
|
||||
if (embed == 0)
|
||||
OPENSSL_free(a);
|
||||
}
|
||||
|
||||
void ASN1_STRING_free(ASN1_STRING *a)
|
||||
{
|
||||
if (a == NULL)
|
||||
return;
|
||||
asn1_string_embed_free(a, a->flags & ASN1_STRING_FLAG_EMBED);
|
||||
}
|
||||
|
||||
void ASN1_STRING_clear_free(ASN1_STRING *a)
|
||||
{
|
||||
if (a == NULL)
|
||||
return;
|
||||
if (a->data && !(a->flags & ASN1_STRING_FLAG_NDEF))
|
||||
OPENSSL_cleanse(a->data, a->length);
|
||||
ASN1_STRING_free(a);
|
||||
}
|
||||
|
||||
int ASN1_STRING_cmp(const ASN1_STRING *a, const ASN1_STRING *b)
|
||||
{
|
||||
int i;
|
||||
|
||||
i = (a->length - b->length);
|
||||
if (i == 0) {
|
||||
i = memcmp(a->data, b->data, a->length);
|
||||
if (i == 0)
|
||||
return a->type - b->type;
|
||||
else
|
||||
return i;
|
||||
} else
|
||||
return i;
|
||||
}
|
||||
|
||||
int ASN1_STRING_length(const ASN1_STRING *x)
|
||||
{
|
||||
return x->length;
|
||||
}
|
||||
|
||||
void ASN1_STRING_length_set(ASN1_STRING *x, int len)
|
||||
{
|
||||
x->length = len;
|
||||
}
|
||||
|
||||
int ASN1_STRING_type(const ASN1_STRING *x)
|
||||
{
|
||||
return x->type;
|
||||
}
|
||||
|
||||
const unsigned char *ASN1_STRING_get0_data(const ASN1_STRING *x)
|
||||
{
|
||||
return x->data;
|
||||
}
|
||||
|
||||
# if OPENSSL_API_COMPAT < 0x10100000L
|
||||
unsigned char *ASN1_STRING_data(ASN1_STRING *x)
|
||||
{
|
||||
return x->data;
|
||||
}
|
||||
#endif
|
||||
83
crypto/asn1/asn1_locl.h
Normal file
83
crypto/asn1/asn1_locl.h
Normal file
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* Copyright 2005-2017 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
/* Internal ASN1 structures and functions: not for application use */
|
||||
|
||||
int asn1_time_to_tm(struct tm *tm, const ASN1_TIME *d);
|
||||
int asn1_utctime_to_tm(struct tm *tm, const ASN1_UTCTIME *d);
|
||||
int asn1_generalizedtime_to_tm(struct tm *tm, const ASN1_GENERALIZEDTIME *d);
|
||||
|
||||
/* ASN1 scan context structure */
|
||||
|
||||
struct asn1_sctx_st {
|
||||
/* The ASN1_ITEM associated with this field */
|
||||
const ASN1_ITEM *it;
|
||||
/* If ASN1_TEMPLATE associated with this field */
|
||||
const ASN1_TEMPLATE *tt;
|
||||
/* Various flags associated with field and context */
|
||||
unsigned long flags;
|
||||
/* If SEQUENCE OF or SET OF, field index */
|
||||
int skidx;
|
||||
/* ASN1 depth of field */
|
||||
int depth;
|
||||
/* Structure and field name */
|
||||
const char *sname, *fname;
|
||||
/* If a primitive type the type of underlying field */
|
||||
int prim_type;
|
||||
/* The field value itself */
|
||||
ASN1_VALUE **field;
|
||||
/* Callback to pass information to */
|
||||
int (*scan_cb) (ASN1_SCTX *ctx);
|
||||
/* Context specific application data */
|
||||
void *app_data;
|
||||
} /* ASN1_SCTX */ ;
|
||||
|
||||
typedef struct mime_param_st MIME_PARAM;
|
||||
DEFINE_STACK_OF(MIME_PARAM)
|
||||
typedef struct mime_header_st MIME_HEADER;
|
||||
DEFINE_STACK_OF(MIME_HEADER)
|
||||
|
||||
void asn1_string_embed_free(ASN1_STRING *a, int embed);
|
||||
|
||||
int asn1_get_choice_selector(ASN1_VALUE **pval, const ASN1_ITEM *it);
|
||||
int asn1_set_choice_selector(ASN1_VALUE **pval, int value,
|
||||
const ASN1_ITEM *it);
|
||||
|
||||
ASN1_VALUE **asn1_get_field_ptr(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt);
|
||||
|
||||
const ASN1_TEMPLATE *asn1_do_adb(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt,
|
||||
int nullerr);
|
||||
|
||||
int asn1_do_lock(ASN1_VALUE **pval, int op, const ASN1_ITEM *it);
|
||||
|
||||
void asn1_enc_init(ASN1_VALUE **pval, const ASN1_ITEM *it);
|
||||
void asn1_enc_free(ASN1_VALUE **pval, const ASN1_ITEM *it);
|
||||
int asn1_enc_restore(int *len, unsigned char **out, ASN1_VALUE **pval,
|
||||
const ASN1_ITEM *it);
|
||||
int asn1_enc_save(ASN1_VALUE **pval, const unsigned char *in, int inlen,
|
||||
const ASN1_ITEM *it);
|
||||
|
||||
void asn1_item_embed_free(ASN1_VALUE **pval, const ASN1_ITEM *it, int embed);
|
||||
void asn1_primitive_free(ASN1_VALUE **pval, const ASN1_ITEM *it, int embed);
|
||||
void asn1_template_free(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt);
|
||||
|
||||
ASN1_OBJECT *c2i_ASN1_OBJECT(ASN1_OBJECT **a, const unsigned char **pp,
|
||||
long length);
|
||||
int i2c_ASN1_BIT_STRING(ASN1_BIT_STRING *a, unsigned char **pp);
|
||||
ASN1_BIT_STRING *c2i_ASN1_BIT_STRING(ASN1_BIT_STRING **a,
|
||||
const unsigned char **pp, long length);
|
||||
int i2c_ASN1_INTEGER(ASN1_INTEGER *a, unsigned char **pp);
|
||||
ASN1_INTEGER *c2i_ASN1_INTEGER(ASN1_INTEGER **a, const unsigned char **pp,
|
||||
long length);
|
||||
|
||||
/* Internal functions used by x_int64.c */
|
||||
int c2i_uint64_int(uint64_t *ret, int *neg, const unsigned char **pp, long len);
|
||||
int i2c_uint64_int(unsigned char *p, uint64_t r, int neg);
|
||||
|
||||
ASN1_TIME *asn1_time_from_tm(ASN1_TIME *s, struct tm *ts, int type);
|
||||
375
crypto/asn1/asn1_par.c
Normal file
375
crypto/asn1/asn1_par.c
Normal file
@@ -0,0 +1,375 @@
|
||||
/*
|
||||
* Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "internal/cryptlib.h"
|
||||
#include <openssl/buffer.h>
|
||||
#include <openssl/objects.h>
|
||||
#include <openssl/asn1.h>
|
||||
|
||||
#ifndef ASN1_PARSE_MAXDEPTH
|
||||
#define ASN1_PARSE_MAXDEPTH 128
|
||||
#endif
|
||||
|
||||
static int asn1_print_info(BIO *bp, int tag, int xclass, int constructed,
|
||||
int indent);
|
||||
static int asn1_parse2(BIO *bp, const unsigned char **pp, long length,
|
||||
int offset, int depth, int indent, int dump);
|
||||
static int asn1_print_info(BIO *bp, int tag, int xclass, int constructed,
|
||||
int indent)
|
||||
{
|
||||
static const char fmt[] = "%-18s";
|
||||
char str[128];
|
||||
const char *p;
|
||||
|
||||
if (constructed & V_ASN1_CONSTRUCTED)
|
||||
p = "cons: ";
|
||||
else
|
||||
p = "prim: ";
|
||||
if (BIO_write(bp, p, 6) < 6)
|
||||
goto err;
|
||||
BIO_indent(bp, indent, 128);
|
||||
|
||||
p = str;
|
||||
if ((xclass & V_ASN1_PRIVATE) == V_ASN1_PRIVATE)
|
||||
BIO_snprintf(str, sizeof(str), "priv [ %d ] ", tag);
|
||||
else if ((xclass & V_ASN1_CONTEXT_SPECIFIC) == V_ASN1_CONTEXT_SPECIFIC)
|
||||
BIO_snprintf(str, sizeof(str), "cont [ %d ]", tag);
|
||||
else if ((xclass & V_ASN1_APPLICATION) == V_ASN1_APPLICATION)
|
||||
BIO_snprintf(str, sizeof(str), "appl [ %d ]", tag);
|
||||
else if (tag > 30)
|
||||
BIO_snprintf(str, sizeof(str), "<ASN1 %d>", tag);
|
||||
else
|
||||
p = ASN1_tag2str(tag);
|
||||
|
||||
if (BIO_printf(bp, fmt, p) <= 0)
|
||||
goto err;
|
||||
return 1;
|
||||
err:
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ASN1_parse(BIO *bp, const unsigned char *pp, long len, int indent)
|
||||
{
|
||||
return asn1_parse2(bp, &pp, len, 0, 0, indent, 0);
|
||||
}
|
||||
|
||||
int ASN1_parse_dump(BIO *bp, const unsigned char *pp, long len, int indent,
|
||||
int dump)
|
||||
{
|
||||
return asn1_parse2(bp, &pp, len, 0, 0, indent, dump);
|
||||
}
|
||||
|
||||
static int asn1_parse2(BIO *bp, const unsigned char **pp, long length,
|
||||
int offset, int depth, int indent, int dump)
|
||||
{
|
||||
const unsigned char *p, *ep, *tot, *op, *opp;
|
||||
long len;
|
||||
int tag, xclass, ret = 0;
|
||||
int nl, hl, j, r;
|
||||
ASN1_OBJECT *o = NULL;
|
||||
ASN1_OCTET_STRING *os = NULL;
|
||||
/* ASN1_BMPSTRING *bmp=NULL; */
|
||||
int dump_indent, dump_cont = 0;
|
||||
|
||||
if (depth > ASN1_PARSE_MAXDEPTH) {
|
||||
BIO_puts(bp, "BAD RECURSION DEPTH\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
dump_indent = 6; /* Because we know BIO_dump_indent() */
|
||||
p = *pp;
|
||||
tot = p + length;
|
||||
while (length > 0) {
|
||||
op = p;
|
||||
j = ASN1_get_object(&p, &len, &tag, &xclass, length);
|
||||
if (j & 0x80) {
|
||||
if (BIO_write(bp, "Error in encoding\n", 18) <= 0)
|
||||
goto end;
|
||||
ret = 0;
|
||||
goto end;
|
||||
}
|
||||
hl = (p - op);
|
||||
length -= hl;
|
||||
/*
|
||||
* if j == 0x21 it is a constructed indefinite length object
|
||||
*/
|
||||
if (BIO_printf(bp, "%5ld:", (long)offset + (long)(op - *pp))
|
||||
<= 0)
|
||||
goto end;
|
||||
|
||||
if (j != (V_ASN1_CONSTRUCTED | 1)) {
|
||||
if (BIO_printf(bp, "d=%-2d hl=%ld l=%4ld ",
|
||||
depth, (long)hl, len) <= 0)
|
||||
goto end;
|
||||
} else {
|
||||
if (BIO_printf(bp, "d=%-2d hl=%ld l=inf ", depth, (long)hl) <= 0)
|
||||
goto end;
|
||||
}
|
||||
if (!asn1_print_info(bp, tag, xclass, j, (indent) ? depth : 0))
|
||||
goto end;
|
||||
if (j & V_ASN1_CONSTRUCTED) {
|
||||
const unsigned char *sp = p;
|
||||
|
||||
ep = p + len;
|
||||
if (BIO_write(bp, "\n", 1) <= 0)
|
||||
goto end;
|
||||
if (len > length) {
|
||||
BIO_printf(bp, "length is greater than %ld\n", length);
|
||||
ret = 0;
|
||||
goto end;
|
||||
}
|
||||
if ((j == 0x21) && (len == 0)) {
|
||||
for (;;) {
|
||||
r = asn1_parse2(bp, &p, (long)(tot - p),
|
||||
offset + (p - *pp), depth + 1,
|
||||
indent, dump);
|
||||
if (r == 0) {
|
||||
ret = 0;
|
||||
goto end;
|
||||
}
|
||||
if ((r == 2) || (p >= tot)) {
|
||||
len = p - sp;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
long tmp = len;
|
||||
|
||||
while (p < ep) {
|
||||
sp = p;
|
||||
r = asn1_parse2(bp, &p, tmp,
|
||||
offset + (p - *pp), depth + 1,
|
||||
indent, dump);
|
||||
if (r == 0) {
|
||||
ret = 0;
|
||||
goto end;
|
||||
}
|
||||
tmp -= p - sp;
|
||||
}
|
||||
}
|
||||
} else if (xclass != 0) {
|
||||
p += len;
|
||||
if (BIO_write(bp, "\n", 1) <= 0)
|
||||
goto end;
|
||||
} else {
|
||||
nl = 0;
|
||||
if ((tag == V_ASN1_PRINTABLESTRING) ||
|
||||
(tag == V_ASN1_T61STRING) ||
|
||||
(tag == V_ASN1_IA5STRING) ||
|
||||
(tag == V_ASN1_VISIBLESTRING) ||
|
||||
(tag == V_ASN1_NUMERICSTRING) ||
|
||||
(tag == V_ASN1_UTF8STRING) ||
|
||||
(tag == V_ASN1_UTCTIME) || (tag == V_ASN1_GENERALIZEDTIME)) {
|
||||
if (BIO_write(bp, ":", 1) <= 0)
|
||||
goto end;
|
||||
if ((len > 0) && BIO_write(bp, (const char *)p, (int)len)
|
||||
!= (int)len)
|
||||
goto end;
|
||||
} else if (tag == V_ASN1_OBJECT) {
|
||||
opp = op;
|
||||
if (d2i_ASN1_OBJECT(&o, &opp, len + hl) != NULL) {
|
||||
if (BIO_write(bp, ":", 1) <= 0)
|
||||
goto end;
|
||||
i2a_ASN1_OBJECT(bp, o);
|
||||
} else {
|
||||
if (BIO_puts(bp, ":BAD OBJECT") <= 0)
|
||||
goto end;
|
||||
dump_cont = 1;
|
||||
}
|
||||
} else if (tag == V_ASN1_BOOLEAN) {
|
||||
if (len != 1) {
|
||||
if (BIO_puts(bp, ":BAD BOOLEAN") <= 0)
|
||||
goto end;
|
||||
dump_cont = 1;
|
||||
}
|
||||
if (len > 0)
|
||||
BIO_printf(bp, ":%u", p[0]);
|
||||
} else if (tag == V_ASN1_BMPSTRING) {
|
||||
/* do the BMP thang */
|
||||
} else if (tag == V_ASN1_OCTET_STRING) {
|
||||
int i, printable = 1;
|
||||
|
||||
opp = op;
|
||||
os = d2i_ASN1_OCTET_STRING(NULL, &opp, len + hl);
|
||||
if (os != NULL && os->length > 0) {
|
||||
opp = os->data;
|
||||
/*
|
||||
* testing whether the octet string is printable
|
||||
*/
|
||||
for (i = 0; i < os->length; i++) {
|
||||
if (((opp[i] < ' ') &&
|
||||
(opp[i] != '\n') &&
|
||||
(opp[i] != '\r') &&
|
||||
(opp[i] != '\t')) || (opp[i] > '~')) {
|
||||
printable = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (printable)
|
||||
/* printable string */
|
||||
{
|
||||
if (BIO_write(bp, ":", 1) <= 0)
|
||||
goto end;
|
||||
if (BIO_write(bp, (const char *)opp, os->length) <= 0)
|
||||
goto end;
|
||||
} else if (!dump)
|
||||
/*
|
||||
* not printable => print octet string as hex dump
|
||||
*/
|
||||
{
|
||||
if (BIO_write(bp, "[HEX DUMP]:", 11) <= 0)
|
||||
goto end;
|
||||
for (i = 0; i < os->length; i++) {
|
||||
if (BIO_printf(bp, "%02X", opp[i]) <= 0)
|
||||
goto end;
|
||||
}
|
||||
} else
|
||||
/* print the normal dump */
|
||||
{
|
||||
if (!nl) {
|
||||
if (BIO_write(bp, "\n", 1) <= 0)
|
||||
goto end;
|
||||
}
|
||||
if (BIO_dump_indent(bp,
|
||||
(const char *)opp,
|
||||
((dump == -1 || dump >
|
||||
os->
|
||||
length) ? os->length : dump),
|
||||
dump_indent) <= 0)
|
||||
goto end;
|
||||
nl = 1;
|
||||
}
|
||||
}
|
||||
ASN1_OCTET_STRING_free(os);
|
||||
os = NULL;
|
||||
} else if (tag == V_ASN1_INTEGER) {
|
||||
ASN1_INTEGER *bs;
|
||||
int i;
|
||||
|
||||
opp = op;
|
||||
bs = d2i_ASN1_INTEGER(NULL, &opp, len + hl);
|
||||
if (bs != NULL) {
|
||||
if (BIO_write(bp, ":", 1) <= 0)
|
||||
goto end;
|
||||
if (bs->type == V_ASN1_NEG_INTEGER)
|
||||
if (BIO_write(bp, "-", 1) <= 0)
|
||||
goto end;
|
||||
for (i = 0; i < bs->length; i++) {
|
||||
if (BIO_printf(bp, "%02X", bs->data[i]) <= 0)
|
||||
goto end;
|
||||
}
|
||||
if (bs->length == 0) {
|
||||
if (BIO_write(bp, "00", 2) <= 0)
|
||||
goto end;
|
||||
}
|
||||
} else {
|
||||
if (BIO_puts(bp, ":BAD INTEGER") <= 0)
|
||||
goto end;
|
||||
dump_cont = 1;
|
||||
}
|
||||
ASN1_INTEGER_free(bs);
|
||||
} else if (tag == V_ASN1_ENUMERATED) {
|
||||
ASN1_ENUMERATED *bs;
|
||||
int i;
|
||||
|
||||
opp = op;
|
||||
bs = d2i_ASN1_ENUMERATED(NULL, &opp, len + hl);
|
||||
if (bs != NULL) {
|
||||
if (BIO_write(bp, ":", 1) <= 0)
|
||||
goto end;
|
||||
if (bs->type == V_ASN1_NEG_ENUMERATED)
|
||||
if (BIO_write(bp, "-", 1) <= 0)
|
||||
goto end;
|
||||
for (i = 0; i < bs->length; i++) {
|
||||
if (BIO_printf(bp, "%02X", bs->data[i]) <= 0)
|
||||
goto end;
|
||||
}
|
||||
if (bs->length == 0) {
|
||||
if (BIO_write(bp, "00", 2) <= 0)
|
||||
goto end;
|
||||
}
|
||||
} else {
|
||||
if (BIO_puts(bp, ":BAD ENUMERATED") <= 0)
|
||||
goto end;
|
||||
dump_cont = 1;
|
||||
}
|
||||
ASN1_ENUMERATED_free(bs);
|
||||
} else if (len > 0 && dump) {
|
||||
if (!nl) {
|
||||
if (BIO_write(bp, "\n", 1) <= 0)
|
||||
goto end;
|
||||
}
|
||||
if (BIO_dump_indent(bp, (const char *)p,
|
||||
((dump == -1 || dump > len) ? len : dump),
|
||||
dump_indent) <= 0)
|
||||
goto end;
|
||||
nl = 1;
|
||||
}
|
||||
if (dump_cont) {
|
||||
int i;
|
||||
const unsigned char *tmp = op + hl;
|
||||
if (BIO_puts(bp, ":[") <= 0)
|
||||
goto end;
|
||||
for (i = 0; i < len; i++) {
|
||||
if (BIO_printf(bp, "%02X", tmp[i]) <= 0)
|
||||
goto end;
|
||||
}
|
||||
if (BIO_puts(bp, "]") <= 0)
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (!nl) {
|
||||
if (BIO_write(bp, "\n", 1) <= 0)
|
||||
goto end;
|
||||
}
|
||||
p += len;
|
||||
if ((tag == V_ASN1_EOC) && (xclass == 0)) {
|
||||
ret = 2; /* End of sequence */
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
length -= len;
|
||||
}
|
||||
ret = 1;
|
||||
end:
|
||||
ASN1_OBJECT_free(o);
|
||||
ASN1_OCTET_STRING_free(os);
|
||||
*pp = p;
|
||||
return ret;
|
||||
}
|
||||
|
||||
const char *ASN1_tag2str(int tag)
|
||||
{
|
||||
static const char *const tag2str[] = {
|
||||
/* 0-4 */
|
||||
"EOC", "BOOLEAN", "INTEGER", "BIT STRING", "OCTET STRING",
|
||||
/* 5-9 */
|
||||
"NULL", "OBJECT", "OBJECT DESCRIPTOR", "EXTERNAL", "REAL",
|
||||
/* 10-13 */
|
||||
"ENUMERATED", "<ASN1 11>", "UTF8STRING", "<ASN1 13>",
|
||||
/* 15-17 */
|
||||
"<ASN1 14>", "<ASN1 15>", "SEQUENCE", "SET",
|
||||
/* 18-20 */
|
||||
"NUMERICSTRING", "PRINTABLESTRING", "T61STRING",
|
||||
/* 21-24 */
|
||||
"VIDEOTEXSTRING", "IA5STRING", "UTCTIME", "GENERALIZEDTIME",
|
||||
/* 25-27 */
|
||||
"GRAPHICSTRING", "VISIBLESTRING", "GENERALSTRING",
|
||||
/* 28-30 */
|
||||
"UNIVERSALSTRING", "<ASN1 29>", "BMPSTRING"
|
||||
};
|
||||
|
||||
if ((tag == V_ASN1_NEG_INTEGER) || (tag == V_ASN1_NEG_ENUMERATED))
|
||||
tag &= ~0x100;
|
||||
|
||||
if (tag < 0 || tag > 30)
|
||||
return "(unknown)";
|
||||
return tag2str[tag];
|
||||
}
|
||||
963
crypto/asn1/asn_mime.c
Normal file
963
crypto/asn1/asn_mime.c
Normal file
@@ -0,0 +1,963 @@
|
||||
/*
|
||||
* Copyright 2008-2018 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "internal/ctype.h"
|
||||
#include "internal/cryptlib.h"
|
||||
#include <openssl/rand.h>
|
||||
#include <openssl/x509.h>
|
||||
#include <openssl/asn1.h>
|
||||
#include <openssl/asn1t.h>
|
||||
#include "internal/evp_int.h"
|
||||
#include "internal/bio.h"
|
||||
#include "asn1_locl.h"
|
||||
|
||||
/*
|
||||
* Generalised MIME like utilities for streaming ASN1. Although many have a
|
||||
* PKCS7/CMS like flavour others are more general purpose.
|
||||
*/
|
||||
|
||||
/*
|
||||
* MIME format structures Note that all are translated to lower case apart
|
||||
* from parameter values. Quotes are stripped off
|
||||
*/
|
||||
|
||||
struct mime_param_st {
|
||||
char *param_name; /* Param name e.g. "micalg" */
|
||||
char *param_value; /* Param value e.g. "sha1" */
|
||||
};
|
||||
|
||||
struct mime_header_st {
|
||||
char *name; /* Name of line e.g. "content-type" */
|
||||
char *value; /* Value of line e.g. "text/plain" */
|
||||
STACK_OF(MIME_PARAM) *params; /* Zero or more parameters */
|
||||
};
|
||||
|
||||
static int asn1_output_data(BIO *out, BIO *data, ASN1_VALUE *val, int flags,
|
||||
const ASN1_ITEM *it);
|
||||
static char *strip_ends(char *name);
|
||||
static char *strip_start(char *name);
|
||||
static char *strip_end(char *name);
|
||||
static MIME_HEADER *mime_hdr_new(const char *name, const char *value);
|
||||
static int mime_hdr_addparam(MIME_HEADER *mhdr, const char *name, const char *value);
|
||||
static STACK_OF(MIME_HEADER) *mime_parse_hdr(BIO *bio);
|
||||
static int mime_hdr_cmp(const MIME_HEADER *const *a,
|
||||
const MIME_HEADER *const *b);
|
||||
static int mime_param_cmp(const MIME_PARAM *const *a,
|
||||
const MIME_PARAM *const *b);
|
||||
static void mime_param_free(MIME_PARAM *param);
|
||||
static int mime_bound_check(char *line, int linelen, const char *bound, int blen);
|
||||
static int multi_split(BIO *bio, const char *bound, STACK_OF(BIO) **ret);
|
||||
static int strip_eol(char *linebuf, int *plen, int flags);
|
||||
static MIME_HEADER *mime_hdr_find(STACK_OF(MIME_HEADER) *hdrs, const char *name);
|
||||
static MIME_PARAM *mime_param_find(MIME_HEADER *hdr, const char *name);
|
||||
static void mime_hdr_free(MIME_HEADER *hdr);
|
||||
|
||||
#define MAX_SMLEN 1024
|
||||
#define mime_debug(x) /* x */
|
||||
|
||||
/* Output an ASN1 structure in BER format streaming if necessary */
|
||||
|
||||
int i2d_ASN1_bio_stream(BIO *out, ASN1_VALUE *val, BIO *in, int flags,
|
||||
const ASN1_ITEM *it)
|
||||
{
|
||||
/* If streaming create stream BIO and copy all content through it */
|
||||
if (flags & SMIME_STREAM) {
|
||||
BIO *bio, *tbio;
|
||||
bio = BIO_new_NDEF(out, val, it);
|
||||
if (!bio) {
|
||||
ASN1err(ASN1_F_I2D_ASN1_BIO_STREAM, ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
SMIME_crlf_copy(in, bio, flags);
|
||||
(void)BIO_flush(bio);
|
||||
/* Free up successive BIOs until we hit the old output BIO */
|
||||
do {
|
||||
tbio = BIO_pop(bio);
|
||||
BIO_free(bio);
|
||||
bio = tbio;
|
||||
} while (bio != out);
|
||||
}
|
||||
/*
|
||||
* else just write out ASN1 structure which will have all content stored
|
||||
* internally
|
||||
*/
|
||||
else
|
||||
ASN1_item_i2d_bio(it, out, val);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Base 64 read and write of ASN1 structure */
|
||||
|
||||
static int B64_write_ASN1(BIO *out, ASN1_VALUE *val, BIO *in, int flags,
|
||||
const ASN1_ITEM *it)
|
||||
{
|
||||
BIO *b64;
|
||||
int r;
|
||||
b64 = BIO_new(BIO_f_base64());
|
||||
if (b64 == NULL) {
|
||||
ASN1err(ASN1_F_B64_WRITE_ASN1, ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
/*
|
||||
* prepend the b64 BIO so all data is base64 encoded.
|
||||
*/
|
||||
out = BIO_push(b64, out);
|
||||
r = i2d_ASN1_bio_stream(out, val, in, flags, it);
|
||||
(void)BIO_flush(out);
|
||||
BIO_pop(out);
|
||||
BIO_free(b64);
|
||||
return r;
|
||||
}
|
||||
|
||||
/* Streaming ASN1 PEM write */
|
||||
|
||||
int PEM_write_bio_ASN1_stream(BIO *out, ASN1_VALUE *val, BIO *in, int flags,
|
||||
const char *hdr, const ASN1_ITEM *it)
|
||||
{
|
||||
int r;
|
||||
BIO_printf(out, "-----BEGIN %s-----\n", hdr);
|
||||
r = B64_write_ASN1(out, val, in, flags, it);
|
||||
BIO_printf(out, "-----END %s-----\n", hdr);
|
||||
return r;
|
||||
}
|
||||
|
||||
static ASN1_VALUE *b64_read_asn1(BIO *bio, const ASN1_ITEM *it)
|
||||
{
|
||||
BIO *b64;
|
||||
ASN1_VALUE *val;
|
||||
|
||||
if ((b64 = BIO_new(BIO_f_base64())) == NULL) {
|
||||
ASN1err(ASN1_F_B64_READ_ASN1, ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
bio = BIO_push(b64, bio);
|
||||
val = ASN1_item_d2i_bio(it, bio, NULL);
|
||||
if (!val)
|
||||
ASN1err(ASN1_F_B64_READ_ASN1, ASN1_R_DECODE_ERROR);
|
||||
(void)BIO_flush(bio);
|
||||
BIO_pop(bio);
|
||||
BIO_free(b64);
|
||||
return val;
|
||||
}
|
||||
|
||||
/* Generate the MIME "micalg" parameter from RFC3851, RFC4490 */
|
||||
|
||||
static int asn1_write_micalg(BIO *out, STACK_OF(X509_ALGOR) *mdalgs)
|
||||
{
|
||||
const EVP_MD *md;
|
||||
int i, have_unknown = 0, write_comma, ret = 0, md_nid;
|
||||
have_unknown = 0;
|
||||
write_comma = 0;
|
||||
for (i = 0; i < sk_X509_ALGOR_num(mdalgs); i++) {
|
||||
if (write_comma)
|
||||
BIO_write(out, ",", 1);
|
||||
write_comma = 1;
|
||||
md_nid = OBJ_obj2nid(sk_X509_ALGOR_value(mdalgs, i)->algorithm);
|
||||
md = EVP_get_digestbynid(md_nid);
|
||||
if (md && md->md_ctrl) {
|
||||
int rv;
|
||||
char *micstr;
|
||||
rv = md->md_ctrl(NULL, EVP_MD_CTRL_MICALG, 0, &micstr);
|
||||
if (rv > 0) {
|
||||
BIO_puts(out, micstr);
|
||||
OPENSSL_free(micstr);
|
||||
continue;
|
||||
}
|
||||
if (rv != -2)
|
||||
goto err;
|
||||
}
|
||||
switch (md_nid) {
|
||||
case NID_sha1:
|
||||
BIO_puts(out, "sha1");
|
||||
break;
|
||||
|
||||
case NID_md5:
|
||||
BIO_puts(out, "md5");
|
||||
break;
|
||||
|
||||
case NID_sha256:
|
||||
BIO_puts(out, "sha-256");
|
||||
break;
|
||||
|
||||
case NID_sha384:
|
||||
BIO_puts(out, "sha-384");
|
||||
break;
|
||||
|
||||
case NID_sha512:
|
||||
BIO_puts(out, "sha-512");
|
||||
break;
|
||||
|
||||
case NID_id_GostR3411_94:
|
||||
BIO_puts(out, "gostr3411-94");
|
||||
goto err;
|
||||
|
||||
default:
|
||||
if (have_unknown)
|
||||
write_comma = 0;
|
||||
else {
|
||||
BIO_puts(out, "unknown");
|
||||
have_unknown = 1;
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
ret = 1;
|
||||
err:
|
||||
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
/* SMIME sender */
|
||||
|
||||
int SMIME_write_ASN1(BIO *bio, ASN1_VALUE *val, BIO *data, int flags,
|
||||
int ctype_nid, int econt_nid,
|
||||
STACK_OF(X509_ALGOR) *mdalgs, const ASN1_ITEM *it)
|
||||
{
|
||||
char bound[33], c;
|
||||
int i;
|
||||
const char *mime_prefix, *mime_eol, *cname = "smime.p7m";
|
||||
const char *msg_type = NULL;
|
||||
if (flags & SMIME_OLDMIME)
|
||||
mime_prefix = "application/x-pkcs7-";
|
||||
else
|
||||
mime_prefix = "application/pkcs7-";
|
||||
|
||||
if (flags & SMIME_CRLFEOL)
|
||||
mime_eol = "\r\n";
|
||||
else
|
||||
mime_eol = "\n";
|
||||
if ((flags & SMIME_DETACHED) && data) {
|
||||
/* We want multipart/signed */
|
||||
/* Generate a random boundary */
|
||||
if (RAND_bytes((unsigned char *)bound, 32) <= 0)
|
||||
return 0;
|
||||
for (i = 0; i < 32; i++) {
|
||||
c = bound[i] & 0xf;
|
||||
if (c < 10)
|
||||
c += '0';
|
||||
else
|
||||
c += 'A' - 10;
|
||||
bound[i] = c;
|
||||
}
|
||||
bound[32] = 0;
|
||||
BIO_printf(bio, "MIME-Version: 1.0%s", mime_eol);
|
||||
BIO_printf(bio, "Content-Type: multipart/signed;");
|
||||
BIO_printf(bio, " protocol=\"%ssignature\";", mime_prefix);
|
||||
BIO_puts(bio, " micalg=\"");
|
||||
asn1_write_micalg(bio, mdalgs);
|
||||
BIO_printf(bio, "\"; boundary=\"----%s\"%s%s",
|
||||
bound, mime_eol, mime_eol);
|
||||
BIO_printf(bio, "This is an S/MIME signed message%s%s",
|
||||
mime_eol, mime_eol);
|
||||
/* Now write out the first part */
|
||||
BIO_printf(bio, "------%s%s", bound, mime_eol);
|
||||
if (!asn1_output_data(bio, data, val, flags, it))
|
||||
return 0;
|
||||
BIO_printf(bio, "%s------%s%s", mime_eol, bound, mime_eol);
|
||||
|
||||
/* Headers for signature */
|
||||
|
||||
BIO_printf(bio, "Content-Type: %ssignature;", mime_prefix);
|
||||
BIO_printf(bio, " name=\"smime.p7s\"%s", mime_eol);
|
||||
BIO_printf(bio, "Content-Transfer-Encoding: base64%s", mime_eol);
|
||||
BIO_printf(bio, "Content-Disposition: attachment;");
|
||||
BIO_printf(bio, " filename=\"smime.p7s\"%s%s", mime_eol, mime_eol);
|
||||
B64_write_ASN1(bio, val, NULL, 0, it);
|
||||
BIO_printf(bio, "%s------%s--%s%s", mime_eol, bound,
|
||||
mime_eol, mime_eol);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Determine smime-type header */
|
||||
|
||||
if (ctype_nid == NID_pkcs7_enveloped)
|
||||
msg_type = "enveloped-data";
|
||||
else if (ctype_nid == NID_pkcs7_signed) {
|
||||
if (econt_nid == NID_id_smime_ct_receipt)
|
||||
msg_type = "signed-receipt";
|
||||
else if (sk_X509_ALGOR_num(mdalgs) >= 0)
|
||||
msg_type = "signed-data";
|
||||
else
|
||||
msg_type = "certs-only";
|
||||
} else if (ctype_nid == NID_id_smime_ct_compressedData) {
|
||||
msg_type = "compressed-data";
|
||||
cname = "smime.p7z";
|
||||
}
|
||||
/* MIME headers */
|
||||
BIO_printf(bio, "MIME-Version: 1.0%s", mime_eol);
|
||||
BIO_printf(bio, "Content-Disposition: attachment;");
|
||||
BIO_printf(bio, " filename=\"%s\"%s", cname, mime_eol);
|
||||
BIO_printf(bio, "Content-Type: %smime;", mime_prefix);
|
||||
if (msg_type)
|
||||
BIO_printf(bio, " smime-type=%s;", msg_type);
|
||||
BIO_printf(bio, " name=\"%s\"%s", cname, mime_eol);
|
||||
BIO_printf(bio, "Content-Transfer-Encoding: base64%s%s",
|
||||
mime_eol, mime_eol);
|
||||
if (!B64_write_ASN1(bio, val, data, flags, it))
|
||||
return 0;
|
||||
BIO_printf(bio, "%s", mime_eol);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Handle output of ASN1 data */
|
||||
|
||||
static int asn1_output_data(BIO *out, BIO *data, ASN1_VALUE *val, int flags,
|
||||
const ASN1_ITEM *it)
|
||||
{
|
||||
BIO *tmpbio;
|
||||
const ASN1_AUX *aux = it->funcs;
|
||||
ASN1_STREAM_ARG sarg;
|
||||
int rv = 1;
|
||||
|
||||
/*
|
||||
* If data is not detached or resigning then the output BIO is already
|
||||
* set up to finalise when it is written through.
|
||||
*/
|
||||
if (!(flags & SMIME_DETACHED) || (flags & PKCS7_REUSE_DIGEST)) {
|
||||
SMIME_crlf_copy(data, out, flags);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!aux || !aux->asn1_cb) {
|
||||
ASN1err(ASN1_F_ASN1_OUTPUT_DATA, ASN1_R_STREAMING_NOT_SUPPORTED);
|
||||
return 0;
|
||||
}
|
||||
|
||||
sarg.out = out;
|
||||
sarg.ndef_bio = NULL;
|
||||
sarg.boundary = NULL;
|
||||
|
||||
/* Let ASN1 code prepend any needed BIOs */
|
||||
|
||||
if (aux->asn1_cb(ASN1_OP_DETACHED_PRE, &val, it, &sarg) <= 0)
|
||||
return 0;
|
||||
|
||||
/* Copy data across, passing through filter BIOs for processing */
|
||||
SMIME_crlf_copy(data, sarg.ndef_bio, flags);
|
||||
|
||||
/* Finalize structure */
|
||||
if (aux->asn1_cb(ASN1_OP_DETACHED_POST, &val, it, &sarg) <= 0)
|
||||
rv = 0;
|
||||
|
||||
/* Now remove any digests prepended to the BIO */
|
||||
|
||||
while (sarg.ndef_bio != out) {
|
||||
tmpbio = BIO_pop(sarg.ndef_bio);
|
||||
BIO_free(sarg.ndef_bio);
|
||||
sarg.ndef_bio = tmpbio;
|
||||
}
|
||||
|
||||
return rv;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* SMIME reader: handle multipart/signed and opaque signing. in multipart
|
||||
* case the content is placed in a memory BIO pointed to by "bcont". In
|
||||
* opaque this is set to NULL
|
||||
*/
|
||||
|
||||
ASN1_VALUE *SMIME_read_ASN1(BIO *bio, BIO **bcont, const ASN1_ITEM *it)
|
||||
{
|
||||
BIO *asnin;
|
||||
STACK_OF(MIME_HEADER) *headers = NULL;
|
||||
STACK_OF(BIO) *parts = NULL;
|
||||
MIME_HEADER *hdr;
|
||||
MIME_PARAM *prm;
|
||||
ASN1_VALUE *val;
|
||||
int ret;
|
||||
|
||||
if (bcont)
|
||||
*bcont = NULL;
|
||||
|
||||
if ((headers = mime_parse_hdr(bio)) == NULL) {
|
||||
ASN1err(ASN1_F_SMIME_READ_ASN1, ASN1_R_MIME_PARSE_ERROR);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ((hdr = mime_hdr_find(headers, "content-type")) == NULL
|
||||
|| hdr->value == NULL) {
|
||||
sk_MIME_HEADER_pop_free(headers, mime_hdr_free);
|
||||
ASN1err(ASN1_F_SMIME_READ_ASN1, ASN1_R_NO_CONTENT_TYPE);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Handle multipart/signed */
|
||||
|
||||
if (strcmp(hdr->value, "multipart/signed") == 0) {
|
||||
/* Split into two parts */
|
||||
prm = mime_param_find(hdr, "boundary");
|
||||
if (!prm || !prm->param_value) {
|
||||
sk_MIME_HEADER_pop_free(headers, mime_hdr_free);
|
||||
ASN1err(ASN1_F_SMIME_READ_ASN1, ASN1_R_NO_MULTIPART_BOUNDARY);
|
||||
return NULL;
|
||||
}
|
||||
ret = multi_split(bio, prm->param_value, &parts);
|
||||
sk_MIME_HEADER_pop_free(headers, mime_hdr_free);
|
||||
if (!ret || (sk_BIO_num(parts) != 2)) {
|
||||
ASN1err(ASN1_F_SMIME_READ_ASN1, ASN1_R_NO_MULTIPART_BODY_FAILURE);
|
||||
sk_BIO_pop_free(parts, BIO_vfree);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Parse the signature piece */
|
||||
asnin = sk_BIO_value(parts, 1);
|
||||
|
||||
if ((headers = mime_parse_hdr(asnin)) == NULL) {
|
||||
ASN1err(ASN1_F_SMIME_READ_ASN1, ASN1_R_MIME_SIG_PARSE_ERROR);
|
||||
sk_BIO_pop_free(parts, BIO_vfree);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Get content type */
|
||||
|
||||
if ((hdr = mime_hdr_find(headers, "content-type")) == NULL
|
||||
|| hdr->value == NULL) {
|
||||
sk_MIME_HEADER_pop_free(headers, mime_hdr_free);
|
||||
ASN1err(ASN1_F_SMIME_READ_ASN1, ASN1_R_NO_SIG_CONTENT_TYPE);
|
||||
sk_BIO_pop_free(parts, BIO_vfree);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (strcmp(hdr->value, "application/x-pkcs7-signature") &&
|
||||
strcmp(hdr->value, "application/pkcs7-signature")) {
|
||||
ASN1err(ASN1_F_SMIME_READ_ASN1, ASN1_R_SIG_INVALID_MIME_TYPE);
|
||||
ERR_add_error_data(2, "type: ", hdr->value);
|
||||
sk_MIME_HEADER_pop_free(headers, mime_hdr_free);
|
||||
sk_BIO_pop_free(parts, BIO_vfree);
|
||||
return NULL;
|
||||
}
|
||||
sk_MIME_HEADER_pop_free(headers, mime_hdr_free);
|
||||
/* Read in ASN1 */
|
||||
if ((val = b64_read_asn1(asnin, it)) == NULL) {
|
||||
ASN1err(ASN1_F_SMIME_READ_ASN1, ASN1_R_ASN1_SIG_PARSE_ERROR);
|
||||
sk_BIO_pop_free(parts, BIO_vfree);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (bcont) {
|
||||
*bcont = sk_BIO_value(parts, 0);
|
||||
BIO_free(asnin);
|
||||
sk_BIO_free(parts);
|
||||
} else
|
||||
sk_BIO_pop_free(parts, BIO_vfree);
|
||||
return val;
|
||||
}
|
||||
|
||||
/* OK, if not multipart/signed try opaque signature */
|
||||
|
||||
if (strcmp(hdr->value, "application/x-pkcs7-mime") &&
|
||||
strcmp(hdr->value, "application/pkcs7-mime")) {
|
||||
ASN1err(ASN1_F_SMIME_READ_ASN1, ASN1_R_INVALID_MIME_TYPE);
|
||||
ERR_add_error_data(2, "type: ", hdr->value);
|
||||
sk_MIME_HEADER_pop_free(headers, mime_hdr_free);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sk_MIME_HEADER_pop_free(headers, mime_hdr_free);
|
||||
|
||||
if ((val = b64_read_asn1(bio, it)) == NULL) {
|
||||
ASN1err(ASN1_F_SMIME_READ_ASN1, ASN1_R_ASN1_PARSE_ERROR);
|
||||
return NULL;
|
||||
}
|
||||
return val;
|
||||
|
||||
}
|
||||
|
||||
/* Copy text from one BIO to another making the output CRLF at EOL */
|
||||
int SMIME_crlf_copy(BIO *in, BIO *out, int flags)
|
||||
{
|
||||
BIO *bf;
|
||||
char eol;
|
||||
int len;
|
||||
char linebuf[MAX_SMLEN];
|
||||
/*
|
||||
* Buffer output so we don't write one line at a time. This is useful
|
||||
* when streaming as we don't end up with one OCTET STRING per line.
|
||||
*/
|
||||
bf = BIO_new(BIO_f_buffer());
|
||||
if (bf == NULL)
|
||||
return 0;
|
||||
out = BIO_push(bf, out);
|
||||
if (flags & SMIME_BINARY) {
|
||||
while ((len = BIO_read(in, linebuf, MAX_SMLEN)) > 0)
|
||||
BIO_write(out, linebuf, len);
|
||||
} else {
|
||||
int eolcnt = 0;
|
||||
if (flags & SMIME_TEXT)
|
||||
BIO_printf(out, "Content-Type: text/plain\r\n\r\n");
|
||||
while ((len = BIO_gets(in, linebuf, MAX_SMLEN)) > 0) {
|
||||
eol = strip_eol(linebuf, &len, flags);
|
||||
if (len) {
|
||||
/* Not EOF: write out all CRLF */
|
||||
if (flags & SMIME_ASCIICRLF) {
|
||||
int i;
|
||||
for (i = 0; i < eolcnt; i++)
|
||||
BIO_write(out, "\r\n", 2);
|
||||
eolcnt = 0;
|
||||
}
|
||||
BIO_write(out, linebuf, len);
|
||||
if (eol)
|
||||
BIO_write(out, "\r\n", 2);
|
||||
} else if (flags & SMIME_ASCIICRLF)
|
||||
eolcnt++;
|
||||
else if (eol)
|
||||
BIO_write(out, "\r\n", 2);
|
||||
}
|
||||
}
|
||||
(void)BIO_flush(out);
|
||||
BIO_pop(out);
|
||||
BIO_free(bf);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Strip off headers if they are text/plain */
|
||||
int SMIME_text(BIO *in, BIO *out)
|
||||
{
|
||||
char iobuf[4096];
|
||||
int len;
|
||||
STACK_OF(MIME_HEADER) *headers;
|
||||
MIME_HEADER *hdr;
|
||||
|
||||
if ((headers = mime_parse_hdr(in)) == NULL) {
|
||||
ASN1err(ASN1_F_SMIME_TEXT, ASN1_R_MIME_PARSE_ERROR);
|
||||
return 0;
|
||||
}
|
||||
if ((hdr = mime_hdr_find(headers, "content-type")) == NULL
|
||||
|| hdr->value == NULL) {
|
||||
ASN1err(ASN1_F_SMIME_TEXT, ASN1_R_MIME_NO_CONTENT_TYPE);
|
||||
sk_MIME_HEADER_pop_free(headers, mime_hdr_free);
|
||||
return 0;
|
||||
}
|
||||
if (strcmp(hdr->value, "text/plain")) {
|
||||
ASN1err(ASN1_F_SMIME_TEXT, ASN1_R_INVALID_MIME_TYPE);
|
||||
ERR_add_error_data(2, "type: ", hdr->value);
|
||||
sk_MIME_HEADER_pop_free(headers, mime_hdr_free);
|
||||
return 0;
|
||||
}
|
||||
sk_MIME_HEADER_pop_free(headers, mime_hdr_free);
|
||||
while ((len = BIO_read(in, iobuf, sizeof(iobuf))) > 0)
|
||||
BIO_write(out, iobuf, len);
|
||||
if (len < 0)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Split a multipart/XXX message body into component parts: result is
|
||||
* canonical parts in a STACK of bios
|
||||
*/
|
||||
|
||||
static int multi_split(BIO *bio, const char *bound, STACK_OF(BIO) **ret)
|
||||
{
|
||||
char linebuf[MAX_SMLEN];
|
||||
int len, blen;
|
||||
int eol = 0, next_eol = 0;
|
||||
BIO *bpart = NULL;
|
||||
STACK_OF(BIO) *parts;
|
||||
char state, part, first;
|
||||
|
||||
blen = strlen(bound);
|
||||
part = 0;
|
||||
state = 0;
|
||||
first = 1;
|
||||
parts = sk_BIO_new_null();
|
||||
*ret = parts;
|
||||
if (*ret == NULL)
|
||||
return 0;
|
||||
while ((len = BIO_gets(bio, linebuf, MAX_SMLEN)) > 0) {
|
||||
state = mime_bound_check(linebuf, len, bound, blen);
|
||||
if (state == 1) {
|
||||
first = 1;
|
||||
part++;
|
||||
} else if (state == 2) {
|
||||
if (!sk_BIO_push(parts, bpart)) {
|
||||
BIO_free(bpart);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
} else if (part) {
|
||||
/* Strip CR+LF from linebuf */
|
||||
next_eol = strip_eol(linebuf, &len, 0);
|
||||
if (first) {
|
||||
first = 0;
|
||||
if (bpart)
|
||||
if (!sk_BIO_push(parts, bpart)) {
|
||||
BIO_free(bpart);
|
||||
return 0;
|
||||
}
|
||||
bpart = BIO_new(BIO_s_mem());
|
||||
if (bpart == NULL)
|
||||
return 0;
|
||||
BIO_set_mem_eof_return(bpart, 0);
|
||||
} else if (eol)
|
||||
BIO_write(bpart, "\r\n", 2);
|
||||
eol = next_eol;
|
||||
if (len)
|
||||
BIO_write(bpart, linebuf, len);
|
||||
}
|
||||
}
|
||||
BIO_free(bpart);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* This is the big one: parse MIME header lines up to message body */
|
||||
|
||||
#define MIME_INVALID 0
|
||||
#define MIME_START 1
|
||||
#define MIME_TYPE 2
|
||||
#define MIME_NAME 3
|
||||
#define MIME_VALUE 4
|
||||
#define MIME_QUOTE 5
|
||||
#define MIME_COMMENT 6
|
||||
|
||||
static STACK_OF(MIME_HEADER) *mime_parse_hdr(BIO *bio)
|
||||
{
|
||||
char *p, *q, c;
|
||||
char *ntmp;
|
||||
char linebuf[MAX_SMLEN];
|
||||
MIME_HEADER *mhdr = NULL, *new_hdr = NULL;
|
||||
STACK_OF(MIME_HEADER) *headers;
|
||||
int len, state, save_state = 0;
|
||||
|
||||
headers = sk_MIME_HEADER_new(mime_hdr_cmp);
|
||||
if (headers == NULL)
|
||||
return NULL;
|
||||
while ((len = BIO_gets(bio, linebuf, MAX_SMLEN)) > 0) {
|
||||
/* If whitespace at line start then continuation line */
|
||||
if (mhdr && ossl_isspace(linebuf[0]))
|
||||
state = MIME_NAME;
|
||||
else
|
||||
state = MIME_START;
|
||||
ntmp = NULL;
|
||||
/* Go through all characters */
|
||||
for (p = linebuf, q = linebuf; (c = *p) && (c != '\r') && (c != '\n');
|
||||
p++) {
|
||||
|
||||
/*
|
||||
* State machine to handle MIME headers if this looks horrible
|
||||
* that's because it *is*
|
||||
*/
|
||||
|
||||
switch (state) {
|
||||
case MIME_START:
|
||||
if (c == ':') {
|
||||
state = MIME_TYPE;
|
||||
*p = 0;
|
||||
ntmp = strip_ends(q);
|
||||
q = p + 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case MIME_TYPE:
|
||||
if (c == ';') {
|
||||
mime_debug("Found End Value\n");
|
||||
*p = 0;
|
||||
new_hdr = mime_hdr_new(ntmp, strip_ends(q));
|
||||
if (new_hdr == NULL)
|
||||
goto err;
|
||||
if (!sk_MIME_HEADER_push(headers, new_hdr))
|
||||
goto err;
|
||||
mhdr = new_hdr;
|
||||
new_hdr = NULL;
|
||||
ntmp = NULL;
|
||||
q = p + 1;
|
||||
state = MIME_NAME;
|
||||
} else if (c == '(') {
|
||||
save_state = state;
|
||||
state = MIME_COMMENT;
|
||||
}
|
||||
break;
|
||||
|
||||
case MIME_COMMENT:
|
||||
if (c == ')') {
|
||||
state = save_state;
|
||||
}
|
||||
break;
|
||||
|
||||
case MIME_NAME:
|
||||
if (c == '=') {
|
||||
state = MIME_VALUE;
|
||||
*p = 0;
|
||||
ntmp = strip_ends(q);
|
||||
q = p + 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case MIME_VALUE:
|
||||
if (c == ';') {
|
||||
state = MIME_NAME;
|
||||
*p = 0;
|
||||
mime_hdr_addparam(mhdr, ntmp, strip_ends(q));
|
||||
ntmp = NULL;
|
||||
q = p + 1;
|
||||
} else if (c == '"') {
|
||||
mime_debug("Found Quote\n");
|
||||
state = MIME_QUOTE;
|
||||
} else if (c == '(') {
|
||||
save_state = state;
|
||||
state = MIME_COMMENT;
|
||||
}
|
||||
break;
|
||||
|
||||
case MIME_QUOTE:
|
||||
if (c == '"') {
|
||||
mime_debug("Found Match Quote\n");
|
||||
state = MIME_VALUE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (state == MIME_TYPE) {
|
||||
new_hdr = mime_hdr_new(ntmp, strip_ends(q));
|
||||
if (new_hdr == NULL)
|
||||
goto err;
|
||||
if (!sk_MIME_HEADER_push(headers, new_hdr))
|
||||
goto err;
|
||||
mhdr = new_hdr;
|
||||
new_hdr = NULL;
|
||||
} else if (state == MIME_VALUE)
|
||||
mime_hdr_addparam(mhdr, ntmp, strip_ends(q));
|
||||
if (p == linebuf)
|
||||
break; /* Blank line means end of headers */
|
||||
}
|
||||
|
||||
return headers;
|
||||
|
||||
err:
|
||||
mime_hdr_free(new_hdr);
|
||||
sk_MIME_HEADER_pop_free(headers, mime_hdr_free);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static char *strip_ends(char *name)
|
||||
{
|
||||
return strip_end(strip_start(name));
|
||||
}
|
||||
|
||||
/* Strip a parameter of whitespace from start of param */
|
||||
static char *strip_start(char *name)
|
||||
{
|
||||
char *p, c;
|
||||
/* Look for first non white space or quote */
|
||||
for (p = name; (c = *p); p++) {
|
||||
if (c == '"') {
|
||||
/* Next char is start of string if non null */
|
||||
if (p[1])
|
||||
return p + 1;
|
||||
/* Else null string */
|
||||
return NULL;
|
||||
}
|
||||
if (!ossl_isspace(c))
|
||||
return p;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* As above but strip from end of string : maybe should handle brackets? */
|
||||
static char *strip_end(char *name)
|
||||
{
|
||||
char *p, c;
|
||||
if (!name)
|
||||
return NULL;
|
||||
/* Look for first non white space or quote */
|
||||
for (p = name + strlen(name) - 1; p >= name; p--) {
|
||||
c = *p;
|
||||
if (c == '"') {
|
||||
if (p - 1 == name)
|
||||
return NULL;
|
||||
*p = 0;
|
||||
return name;
|
||||
}
|
||||
if (ossl_isspace(c))
|
||||
*p = 0;
|
||||
else
|
||||
return name;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static MIME_HEADER *mime_hdr_new(const char *name, const char *value)
|
||||
{
|
||||
MIME_HEADER *mhdr = NULL;
|
||||
char *tmpname = NULL, *tmpval = NULL, *p;
|
||||
|
||||
if (name) {
|
||||
if ((tmpname = OPENSSL_strdup(name)) == NULL)
|
||||
return NULL;
|
||||
for (p = tmpname; *p; p++)
|
||||
*p = ossl_tolower(*p);
|
||||
}
|
||||
if (value) {
|
||||
if ((tmpval = OPENSSL_strdup(value)) == NULL)
|
||||
goto err;
|
||||
for (p = tmpval; *p; p++)
|
||||
*p = ossl_tolower(*p);
|
||||
}
|
||||
mhdr = OPENSSL_malloc(sizeof(*mhdr));
|
||||
if (mhdr == NULL)
|
||||
goto err;
|
||||
mhdr->name = tmpname;
|
||||
mhdr->value = tmpval;
|
||||
if ((mhdr->params = sk_MIME_PARAM_new(mime_param_cmp)) == NULL)
|
||||
goto err;
|
||||
return mhdr;
|
||||
|
||||
err:
|
||||
OPENSSL_free(tmpname);
|
||||
OPENSSL_free(tmpval);
|
||||
OPENSSL_free(mhdr);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int mime_hdr_addparam(MIME_HEADER *mhdr, const char *name, const char *value)
|
||||
{
|
||||
char *tmpname = NULL, *tmpval = NULL, *p;
|
||||
MIME_PARAM *mparam = NULL;
|
||||
|
||||
if (name) {
|
||||
tmpname = OPENSSL_strdup(name);
|
||||
if (!tmpname)
|
||||
goto err;
|
||||
for (p = tmpname; *p; p++)
|
||||
*p = ossl_tolower(*p);
|
||||
}
|
||||
if (value) {
|
||||
tmpval = OPENSSL_strdup(value);
|
||||
if (!tmpval)
|
||||
goto err;
|
||||
}
|
||||
/* Parameter values are case sensitive so leave as is */
|
||||
mparam = OPENSSL_malloc(sizeof(*mparam));
|
||||
if (mparam == NULL)
|
||||
goto err;
|
||||
mparam->param_name = tmpname;
|
||||
mparam->param_value = tmpval;
|
||||
if (!sk_MIME_PARAM_push(mhdr->params, mparam))
|
||||
goto err;
|
||||
return 1;
|
||||
err:
|
||||
OPENSSL_free(tmpname);
|
||||
OPENSSL_free(tmpval);
|
||||
OPENSSL_free(mparam);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mime_hdr_cmp(const MIME_HEADER *const *a,
|
||||
const MIME_HEADER *const *b)
|
||||
{
|
||||
if (!(*a)->name || !(*b)->name)
|
||||
return ! !(*a)->name - ! !(*b)->name;
|
||||
|
||||
return strcmp((*a)->name, (*b)->name);
|
||||
}
|
||||
|
||||
static int mime_param_cmp(const MIME_PARAM *const *a,
|
||||
const MIME_PARAM *const *b)
|
||||
{
|
||||
if (!(*a)->param_name || !(*b)->param_name)
|
||||
return ! !(*a)->param_name - ! !(*b)->param_name;
|
||||
return strcmp((*a)->param_name, (*b)->param_name);
|
||||
}
|
||||
|
||||
/* Find a header with a given name (if possible) */
|
||||
|
||||
static MIME_HEADER *mime_hdr_find(STACK_OF(MIME_HEADER) *hdrs, const char *name)
|
||||
{
|
||||
MIME_HEADER htmp;
|
||||
int idx;
|
||||
|
||||
htmp.name = (char *)name;
|
||||
htmp.value = NULL;
|
||||
htmp.params = NULL;
|
||||
|
||||
idx = sk_MIME_HEADER_find(hdrs, &htmp);
|
||||
return sk_MIME_HEADER_value(hdrs, idx);
|
||||
}
|
||||
|
||||
static MIME_PARAM *mime_param_find(MIME_HEADER *hdr, const char *name)
|
||||
{
|
||||
MIME_PARAM param;
|
||||
int idx;
|
||||
|
||||
param.param_name = (char *)name;
|
||||
param.param_value = NULL;
|
||||
idx = sk_MIME_PARAM_find(hdr->params, ¶m);
|
||||
return sk_MIME_PARAM_value(hdr->params, idx);
|
||||
}
|
||||
|
||||
static void mime_hdr_free(MIME_HEADER *hdr)
|
||||
{
|
||||
if (hdr == NULL)
|
||||
return;
|
||||
OPENSSL_free(hdr->name);
|
||||
OPENSSL_free(hdr->value);
|
||||
if (hdr->params)
|
||||
sk_MIME_PARAM_pop_free(hdr->params, mime_param_free);
|
||||
OPENSSL_free(hdr);
|
||||
}
|
||||
|
||||
static void mime_param_free(MIME_PARAM *param)
|
||||
{
|
||||
OPENSSL_free(param->param_name);
|
||||
OPENSSL_free(param->param_value);
|
||||
OPENSSL_free(param);
|
||||
}
|
||||
|
||||
/*-
|
||||
* Check for a multipart boundary. Returns:
|
||||
* 0 : no boundary
|
||||
* 1 : part boundary
|
||||
* 2 : final boundary
|
||||
*/
|
||||
static int mime_bound_check(char *line, int linelen, const char *bound, int blen)
|
||||
{
|
||||
if (linelen == -1)
|
||||
linelen = strlen(line);
|
||||
if (blen == -1)
|
||||
blen = strlen(bound);
|
||||
/* Quickly eliminate if line length too short */
|
||||
if (blen + 2 > linelen)
|
||||
return 0;
|
||||
/* Check for part boundary */
|
||||
if ((strncmp(line, "--", 2) == 0)
|
||||
&& strncmp(line + 2, bound, blen) == 0) {
|
||||
if (strncmp(line + blen + 2, "--", 2) == 0)
|
||||
return 2;
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int strip_eol(char *linebuf, int *plen, int flags)
|
||||
{
|
||||
int len = *plen;
|
||||
char *p, c;
|
||||
int is_eol = 0;
|
||||
|
||||
for (p = linebuf + len - 1; len > 0; len--, p--) {
|
||||
c = *p;
|
||||
if (c == '\n') {
|
||||
is_eol = 1;
|
||||
} else if (is_eol && flags & SMIME_ASCIICRLF && c == 32) {
|
||||
/* Strip trailing space on a line; 32 == ASCII for ' ' */
|
||||
continue;
|
||||
} else if (c != '\r') {
|
||||
break;
|
||||
}
|
||||
}
|
||||
*plen = len;
|
||||
return is_eol;
|
||||
}
|
||||
100
crypto/asn1/asn_moid.c
Normal file
100
crypto/asn1/asn_moid.c
Normal file
@@ -0,0 +1,100 @@
|
||||
/*
|
||||
* Copyright 2002-2018 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "internal/ctype.h"
|
||||
#include <openssl/crypto.h>
|
||||
#include "internal/cryptlib.h"
|
||||
#include <openssl/conf.h>
|
||||
#include <openssl/x509.h>
|
||||
#include "internal/asn1_int.h"
|
||||
#include "internal/objects.h"
|
||||
|
||||
/* Simple ASN1 OID module: add all objects in a given section */
|
||||
|
||||
static int do_create(const char *value, const char *name);
|
||||
|
||||
static int oid_module_init(CONF_IMODULE *md, const CONF *cnf)
|
||||
{
|
||||
int i;
|
||||
const char *oid_section;
|
||||
STACK_OF(CONF_VALUE) *sktmp;
|
||||
CONF_VALUE *oval;
|
||||
|
||||
oid_section = CONF_imodule_get_value(md);
|
||||
if ((sktmp = NCONF_get_section(cnf, oid_section)) == NULL) {
|
||||
ASN1err(ASN1_F_OID_MODULE_INIT, ASN1_R_ERROR_LOADING_SECTION);
|
||||
return 0;
|
||||
}
|
||||
for (i = 0; i < sk_CONF_VALUE_num(sktmp); i++) {
|
||||
oval = sk_CONF_VALUE_value(sktmp, i);
|
||||
if (!do_create(oval->value, oval->name)) {
|
||||
ASN1err(ASN1_F_OID_MODULE_INIT, ASN1_R_ADDING_OBJECT);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void oid_module_finish(CONF_IMODULE *md)
|
||||
{
|
||||
}
|
||||
|
||||
void ASN1_add_oid_module(void)
|
||||
{
|
||||
CONF_module_add("oid_section", oid_module_init, oid_module_finish);
|
||||
}
|
||||
|
||||
/*-
|
||||
* Create an OID based on a name value pair. Accept two formats.
|
||||
* shortname = 1.2.3.4
|
||||
* shortname = some long name, 1.2.3.4
|
||||
*/
|
||||
|
||||
static int do_create(const char *value, const char *name)
|
||||
{
|
||||
int nid;
|
||||
const char *ln, *ostr, *p;
|
||||
char *lntmp = NULL;
|
||||
|
||||
p = strrchr(value, ',');
|
||||
if (p == NULL) {
|
||||
ln = name;
|
||||
ostr = value;
|
||||
} else {
|
||||
ln = value;
|
||||
ostr = p + 1;
|
||||
if (*ostr == '\0')
|
||||
return 0;
|
||||
while (ossl_isspace(*ostr))
|
||||
ostr++;
|
||||
while (ossl_isspace(*ln))
|
||||
ln++;
|
||||
p--;
|
||||
while (ossl_isspace(*p)) {
|
||||
if (p == ln)
|
||||
return 0;
|
||||
p--;
|
||||
}
|
||||
p++;
|
||||
if ((lntmp = OPENSSL_malloc((p - ln) + 1)) == NULL) {
|
||||
ASN1err(ASN1_F_DO_CREATE, ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
memcpy(lntmp, ln, p - ln);
|
||||
lntmp[p - ln] = '\0';
|
||||
ln = lntmp;
|
||||
}
|
||||
|
||||
nid = OBJ_create(ostr, name, ln);
|
||||
|
||||
OPENSSL_free(lntmp);
|
||||
|
||||
return nid != NID_undef;
|
||||
}
|
||||
113
crypto/asn1/asn_mstbl.c
Normal file
113
crypto/asn1/asn_mstbl.c
Normal file
@@ -0,0 +1,113 @@
|
||||
/*
|
||||
* Copyright 2012-2017 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <openssl/crypto.h>
|
||||
#include "internal/cryptlib.h"
|
||||
#include <openssl/conf.h>
|
||||
#include <openssl/x509v3.h>
|
||||
|
||||
/* Multi string module: add table entries from a given section */
|
||||
|
||||
static int do_tcreate(const char *value, const char *name);
|
||||
|
||||
static int stbl_module_init(CONF_IMODULE *md, const CONF *cnf)
|
||||
{
|
||||
int i;
|
||||
const char *stbl_section;
|
||||
STACK_OF(CONF_VALUE) *sktmp;
|
||||
CONF_VALUE *mval;
|
||||
|
||||
stbl_section = CONF_imodule_get_value(md);
|
||||
if ((sktmp = NCONF_get_section(cnf, stbl_section)) == NULL) {
|
||||
ASN1err(ASN1_F_STBL_MODULE_INIT, ASN1_R_ERROR_LOADING_SECTION);
|
||||
return 0;
|
||||
}
|
||||
for (i = 0; i < sk_CONF_VALUE_num(sktmp); i++) {
|
||||
mval = sk_CONF_VALUE_value(sktmp, i);
|
||||
if (!do_tcreate(mval->value, mval->name)) {
|
||||
ASN1err(ASN1_F_STBL_MODULE_INIT, ASN1_R_INVALID_VALUE);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void stbl_module_finish(CONF_IMODULE *md)
|
||||
{
|
||||
ASN1_STRING_TABLE_cleanup();
|
||||
}
|
||||
|
||||
void ASN1_add_stable_module(void)
|
||||
{
|
||||
CONF_module_add("stbl_section", stbl_module_init, stbl_module_finish);
|
||||
}
|
||||
|
||||
/*
|
||||
* Create an table entry based on a name value pair. format is oid_name =
|
||||
* n1:v1, n2:v2,... where name is "min", "max", "mask" or "flags".
|
||||
*/
|
||||
|
||||
static int do_tcreate(const char *value, const char *name)
|
||||
{
|
||||
char *eptr;
|
||||
int nid, i, rv = 0;
|
||||
long tbl_min = -1, tbl_max = -1;
|
||||
unsigned long tbl_mask = 0, tbl_flags = 0;
|
||||
STACK_OF(CONF_VALUE) *lst = NULL;
|
||||
CONF_VALUE *cnf = NULL;
|
||||
nid = OBJ_sn2nid(name);
|
||||
if (nid == NID_undef)
|
||||
nid = OBJ_ln2nid(name);
|
||||
if (nid == NID_undef)
|
||||
goto err;
|
||||
lst = X509V3_parse_list(value);
|
||||
if (!lst)
|
||||
goto err;
|
||||
for (i = 0; i < sk_CONF_VALUE_num(lst); i++) {
|
||||
cnf = sk_CONF_VALUE_value(lst, i);
|
||||
if (strcmp(cnf->name, "min") == 0) {
|
||||
tbl_min = strtoul(cnf->value, &eptr, 0);
|
||||
if (*eptr)
|
||||
goto err;
|
||||
} else if (strcmp(cnf->name, "max") == 0) {
|
||||
tbl_max = strtoul(cnf->value, &eptr, 0);
|
||||
if (*eptr)
|
||||
goto err;
|
||||
} else if (strcmp(cnf->name, "mask") == 0) {
|
||||
if (!ASN1_str2mask(cnf->value, &tbl_mask) || !tbl_mask)
|
||||
goto err;
|
||||
} else if (strcmp(cnf->name, "flags") == 0) {
|
||||
if (strcmp(cnf->value, "nomask") == 0)
|
||||
tbl_flags = STABLE_NO_MASK;
|
||||
else if (strcmp(cnf->value, "none") == 0)
|
||||
tbl_flags = STABLE_FLAGS_CLEAR;
|
||||
else
|
||||
goto err;
|
||||
} else
|
||||
goto err;
|
||||
}
|
||||
rv = 1;
|
||||
err:
|
||||
if (rv == 0) {
|
||||
ASN1err(ASN1_F_DO_TCREATE, ASN1_R_INVALID_STRING_TABLE_VALUE);
|
||||
if (cnf)
|
||||
ERR_add_error_data(4, "field=", cnf->name,
|
||||
", value=", cnf->value);
|
||||
else
|
||||
ERR_add_error_data(4, "name=", name, ", value=", value);
|
||||
} else {
|
||||
rv = ASN1_STRING_TABLE_add(nid, tbl_min, tbl_max,
|
||||
tbl_mask, tbl_flags);
|
||||
if (!rv)
|
||||
ASN1err(ASN1_F_DO_TCREATE, ERR_R_MALLOC_FAILURE);
|
||||
}
|
||||
sk_CONF_VALUE_pop_free(lst, X509V3_conf_free);
|
||||
return rv;
|
||||
}
|
||||
62
crypto/asn1/asn_pack.c
Normal file
62
crypto/asn1/asn_pack.c
Normal file
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "internal/cryptlib.h"
|
||||
#include <openssl/asn1.h>
|
||||
|
||||
/* ASN1 packing and unpacking functions */
|
||||
|
||||
ASN1_STRING *ASN1_item_pack(void *obj, const ASN1_ITEM *it, ASN1_STRING **oct)
|
||||
{
|
||||
ASN1_STRING *octmp;
|
||||
|
||||
if (oct == NULL || *oct == NULL) {
|
||||
if ((octmp = ASN1_STRING_new()) == NULL) {
|
||||
ASN1err(ASN1_F_ASN1_ITEM_PACK, ERR_R_MALLOC_FAILURE);
|
||||
return NULL;
|
||||
}
|
||||
} else {
|
||||
octmp = *oct;
|
||||
}
|
||||
|
||||
OPENSSL_free(octmp->data);
|
||||
octmp->data = NULL;
|
||||
|
||||
if ((octmp->length = ASN1_item_i2d(obj, &octmp->data, it)) == 0) {
|
||||
ASN1err(ASN1_F_ASN1_ITEM_PACK, ASN1_R_ENCODE_ERROR);
|
||||
goto err;
|
||||
}
|
||||
if (octmp->data == NULL) {
|
||||
ASN1err(ASN1_F_ASN1_ITEM_PACK, ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (oct != NULL && *oct == NULL)
|
||||
*oct = octmp;
|
||||
|
||||
return octmp;
|
||||
err:
|
||||
if (oct == NULL || *oct == NULL)
|
||||
ASN1_STRING_free(octmp);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Extract an ASN1 object from an ASN1_STRING */
|
||||
|
||||
void *ASN1_item_unpack(const ASN1_STRING *oct, const ASN1_ITEM *it)
|
||||
{
|
||||
const unsigned char *p;
|
||||
void *ret;
|
||||
|
||||
p = oct->data;
|
||||
if ((ret = ASN1_item_d2i(NULL, &p, oct->length, it)) == NULL)
|
||||
ASN1err(ASN1_F_ASN1_ITEM_UNPACK, ASN1_R_DECODE_ERROR);
|
||||
return ret;
|
||||
}
|
||||
444
crypto/asn1/bio_asn1.c
Normal file
444
crypto/asn1/bio_asn1.c
Normal file
@@ -0,0 +1,444 @@
|
||||
/*
|
||||
* Copyright 2006-2018 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
/*
|
||||
* Experimental ASN1 BIO. When written through the data is converted to an
|
||||
* ASN1 string type: default is OCTET STRING. Additional functions can be
|
||||
* provided to add prefix and suffix data.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include "internal/bio.h"
|
||||
#include <openssl/asn1.h>
|
||||
#include "internal/cryptlib.h"
|
||||
|
||||
/* Must be large enough for biggest tag+length */
|
||||
#define DEFAULT_ASN1_BUF_SIZE 20
|
||||
|
||||
typedef enum {
|
||||
ASN1_STATE_START,
|
||||
ASN1_STATE_PRE_COPY,
|
||||
ASN1_STATE_HEADER,
|
||||
ASN1_STATE_HEADER_COPY,
|
||||
ASN1_STATE_DATA_COPY,
|
||||
ASN1_STATE_POST_COPY,
|
||||
ASN1_STATE_DONE
|
||||
} asn1_bio_state_t;
|
||||
|
||||
typedef struct BIO_ASN1_EX_FUNCS_st {
|
||||
asn1_ps_func *ex_func;
|
||||
asn1_ps_func *ex_free_func;
|
||||
} BIO_ASN1_EX_FUNCS;
|
||||
|
||||
typedef struct BIO_ASN1_BUF_CTX_t {
|
||||
/* Internal state */
|
||||
asn1_bio_state_t state;
|
||||
/* Internal buffer */
|
||||
unsigned char *buf;
|
||||
/* Size of buffer */
|
||||
int bufsize;
|
||||
/* Current position in buffer */
|
||||
int bufpos;
|
||||
/* Current buffer length */
|
||||
int buflen;
|
||||
/* Amount of data to copy */
|
||||
int copylen;
|
||||
/* Class and tag to use */
|
||||
int asn1_class, asn1_tag;
|
||||
asn1_ps_func *prefix, *prefix_free, *suffix, *suffix_free;
|
||||
/* Extra buffer for prefix and suffix data */
|
||||
unsigned char *ex_buf;
|
||||
int ex_len;
|
||||
int ex_pos;
|
||||
void *ex_arg;
|
||||
} BIO_ASN1_BUF_CTX;
|
||||
|
||||
static int asn1_bio_write(BIO *h, const char *buf, int num);
|
||||
static int asn1_bio_read(BIO *h, char *buf, int size);
|
||||
static int asn1_bio_puts(BIO *h, const char *str);
|
||||
static int asn1_bio_gets(BIO *h, char *str, int size);
|
||||
static long asn1_bio_ctrl(BIO *h, int cmd, long arg1, void *arg2);
|
||||
static int asn1_bio_new(BIO *h);
|
||||
static int asn1_bio_free(BIO *data);
|
||||
static long asn1_bio_callback_ctrl(BIO *h, int cmd, BIO_info_cb *fp);
|
||||
|
||||
static int asn1_bio_init(BIO_ASN1_BUF_CTX *ctx, int size);
|
||||
static int asn1_bio_flush_ex(BIO *b, BIO_ASN1_BUF_CTX *ctx,
|
||||
asn1_ps_func *cleanup, asn1_bio_state_t next);
|
||||
static int asn1_bio_setup_ex(BIO *b, BIO_ASN1_BUF_CTX *ctx,
|
||||
asn1_ps_func *setup,
|
||||
asn1_bio_state_t ex_state,
|
||||
asn1_bio_state_t other_state);
|
||||
|
||||
static const BIO_METHOD methods_asn1 = {
|
||||
BIO_TYPE_ASN1,
|
||||
"asn1",
|
||||
/* TODO: Convert to new style write function */
|
||||
bwrite_conv,
|
||||
asn1_bio_write,
|
||||
/* TODO: Convert to new style read function */
|
||||
bread_conv,
|
||||
asn1_bio_read,
|
||||
asn1_bio_puts,
|
||||
asn1_bio_gets,
|
||||
asn1_bio_ctrl,
|
||||
asn1_bio_new,
|
||||
asn1_bio_free,
|
||||
asn1_bio_callback_ctrl,
|
||||
};
|
||||
|
||||
const BIO_METHOD *BIO_f_asn1(void)
|
||||
{
|
||||
return &methods_asn1;
|
||||
}
|
||||
|
||||
static int asn1_bio_new(BIO *b)
|
||||
{
|
||||
BIO_ASN1_BUF_CTX *ctx = OPENSSL_zalloc(sizeof(*ctx));
|
||||
|
||||
if (ctx == NULL)
|
||||
return 0;
|
||||
if (!asn1_bio_init(ctx, DEFAULT_ASN1_BUF_SIZE)) {
|
||||
OPENSSL_free(ctx);
|
||||
return 0;
|
||||
}
|
||||
BIO_set_data(b, ctx);
|
||||
BIO_set_init(b, 1);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int asn1_bio_init(BIO_ASN1_BUF_CTX *ctx, int size)
|
||||
{
|
||||
if ((ctx->buf = OPENSSL_malloc(size)) == NULL) {
|
||||
ASN1err(ASN1_F_ASN1_BIO_INIT, ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
ctx->bufsize = size;
|
||||
ctx->asn1_class = V_ASN1_UNIVERSAL;
|
||||
ctx->asn1_tag = V_ASN1_OCTET_STRING;
|
||||
ctx->state = ASN1_STATE_START;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int asn1_bio_free(BIO *b)
|
||||
{
|
||||
BIO_ASN1_BUF_CTX *ctx;
|
||||
|
||||
if (b == NULL)
|
||||
return 0;
|
||||
|
||||
ctx = BIO_get_data(b);
|
||||
if (ctx == NULL)
|
||||
return 0;
|
||||
|
||||
OPENSSL_free(ctx->buf);
|
||||
OPENSSL_free(ctx);
|
||||
BIO_set_data(b, NULL);
|
||||
BIO_set_init(b, 0);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int asn1_bio_write(BIO *b, const char *in, int inl)
|
||||
{
|
||||
BIO_ASN1_BUF_CTX *ctx;
|
||||
int wrmax, wrlen, ret;
|
||||
unsigned char *p;
|
||||
BIO *next;
|
||||
|
||||
ctx = BIO_get_data(b);
|
||||
next = BIO_next(b);
|
||||
if (in == NULL || inl < 0 || ctx == NULL || next == NULL)
|
||||
return 0;
|
||||
|
||||
wrlen = 0;
|
||||
ret = -1;
|
||||
|
||||
for (;;) {
|
||||
switch (ctx->state) {
|
||||
/* Setup prefix data, call it */
|
||||
case ASN1_STATE_START:
|
||||
if (!asn1_bio_setup_ex(b, ctx, ctx->prefix,
|
||||
ASN1_STATE_PRE_COPY, ASN1_STATE_HEADER))
|
||||
return 0;
|
||||
break;
|
||||
|
||||
/* Copy any pre data first */
|
||||
case ASN1_STATE_PRE_COPY:
|
||||
|
||||
ret = asn1_bio_flush_ex(b, ctx, ctx->prefix_free,
|
||||
ASN1_STATE_HEADER);
|
||||
|
||||
if (ret <= 0)
|
||||
goto done;
|
||||
|
||||
break;
|
||||
|
||||
case ASN1_STATE_HEADER:
|
||||
ctx->buflen = ASN1_object_size(0, inl, ctx->asn1_tag) - inl;
|
||||
if (!ossl_assert(ctx->buflen <= ctx->bufsize))
|
||||
return 0;
|
||||
p = ctx->buf;
|
||||
ASN1_put_object(&p, 0, inl, ctx->asn1_tag, ctx->asn1_class);
|
||||
ctx->copylen = inl;
|
||||
ctx->state = ASN1_STATE_HEADER_COPY;
|
||||
|
||||
break;
|
||||
|
||||
case ASN1_STATE_HEADER_COPY:
|
||||
ret = BIO_write(next, ctx->buf + ctx->bufpos, ctx->buflen);
|
||||
if (ret <= 0)
|
||||
goto done;
|
||||
|
||||
ctx->buflen -= ret;
|
||||
if (ctx->buflen)
|
||||
ctx->bufpos += ret;
|
||||
else {
|
||||
ctx->bufpos = 0;
|
||||
ctx->state = ASN1_STATE_DATA_COPY;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case ASN1_STATE_DATA_COPY:
|
||||
|
||||
if (inl > ctx->copylen)
|
||||
wrmax = ctx->copylen;
|
||||
else
|
||||
wrmax = inl;
|
||||
ret = BIO_write(next, in, wrmax);
|
||||
if (ret <= 0)
|
||||
goto done;
|
||||
wrlen += ret;
|
||||
ctx->copylen -= ret;
|
||||
in += ret;
|
||||
inl -= ret;
|
||||
|
||||
if (ctx->copylen == 0)
|
||||
ctx->state = ASN1_STATE_HEADER;
|
||||
|
||||
if (inl == 0)
|
||||
goto done;
|
||||
|
||||
break;
|
||||
|
||||
case ASN1_STATE_POST_COPY:
|
||||
case ASN1_STATE_DONE:
|
||||
BIO_clear_retry_flags(b);
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
done:
|
||||
BIO_clear_retry_flags(b);
|
||||
BIO_copy_next_retry(b);
|
||||
|
||||
return (wrlen > 0) ? wrlen : ret;
|
||||
|
||||
}
|
||||
|
||||
static int asn1_bio_flush_ex(BIO *b, BIO_ASN1_BUF_CTX *ctx,
|
||||
asn1_ps_func *cleanup, asn1_bio_state_t next)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (ctx->ex_len <= 0)
|
||||
return 1;
|
||||
for (;;) {
|
||||
ret = BIO_write(BIO_next(b), ctx->ex_buf + ctx->ex_pos, ctx->ex_len);
|
||||
if (ret <= 0)
|
||||
break;
|
||||
ctx->ex_len -= ret;
|
||||
if (ctx->ex_len > 0)
|
||||
ctx->ex_pos += ret;
|
||||
else {
|
||||
if (cleanup)
|
||||
cleanup(b, &ctx->ex_buf, &ctx->ex_len, &ctx->ex_arg);
|
||||
ctx->state = next;
|
||||
ctx->ex_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int asn1_bio_setup_ex(BIO *b, BIO_ASN1_BUF_CTX *ctx,
|
||||
asn1_ps_func *setup,
|
||||
asn1_bio_state_t ex_state,
|
||||
asn1_bio_state_t other_state)
|
||||
{
|
||||
if (setup && !setup(b, &ctx->ex_buf, &ctx->ex_len, &ctx->ex_arg)) {
|
||||
BIO_clear_retry_flags(b);
|
||||
return 0;
|
||||
}
|
||||
if (ctx->ex_len > 0)
|
||||
ctx->state = ex_state;
|
||||
else
|
||||
ctx->state = other_state;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int asn1_bio_read(BIO *b, char *in, int inl)
|
||||
{
|
||||
BIO *next = BIO_next(b);
|
||||
if (next == NULL)
|
||||
return 0;
|
||||
return BIO_read(next, in, inl);
|
||||
}
|
||||
|
||||
static int asn1_bio_puts(BIO *b, const char *str)
|
||||
{
|
||||
return asn1_bio_write(b, str, strlen(str));
|
||||
}
|
||||
|
||||
static int asn1_bio_gets(BIO *b, char *str, int size)
|
||||
{
|
||||
BIO *next = BIO_next(b);
|
||||
if (next == NULL)
|
||||
return 0;
|
||||
return BIO_gets(next, str, size);
|
||||
}
|
||||
|
||||
static long asn1_bio_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp)
|
||||
{
|
||||
BIO *next = BIO_next(b);
|
||||
if (next == NULL)
|
||||
return 0;
|
||||
return BIO_callback_ctrl(next, cmd, fp);
|
||||
}
|
||||
|
||||
static long asn1_bio_ctrl(BIO *b, int cmd, long arg1, void *arg2)
|
||||
{
|
||||
BIO_ASN1_BUF_CTX *ctx;
|
||||
BIO_ASN1_EX_FUNCS *ex_func;
|
||||
long ret = 1;
|
||||
BIO *next;
|
||||
|
||||
ctx = BIO_get_data(b);
|
||||
if (ctx == NULL)
|
||||
return 0;
|
||||
next = BIO_next(b);
|
||||
switch (cmd) {
|
||||
|
||||
case BIO_C_SET_PREFIX:
|
||||
ex_func = arg2;
|
||||
ctx->prefix = ex_func->ex_func;
|
||||
ctx->prefix_free = ex_func->ex_free_func;
|
||||
break;
|
||||
|
||||
case BIO_C_GET_PREFIX:
|
||||
ex_func = arg2;
|
||||
ex_func->ex_func = ctx->prefix;
|
||||
ex_func->ex_free_func = ctx->prefix_free;
|
||||
break;
|
||||
|
||||
case BIO_C_SET_SUFFIX:
|
||||
ex_func = arg2;
|
||||
ctx->suffix = ex_func->ex_func;
|
||||
ctx->suffix_free = ex_func->ex_free_func;
|
||||
break;
|
||||
|
||||
case BIO_C_GET_SUFFIX:
|
||||
ex_func = arg2;
|
||||
ex_func->ex_func = ctx->suffix;
|
||||
ex_func->ex_free_func = ctx->suffix_free;
|
||||
break;
|
||||
|
||||
case BIO_C_SET_EX_ARG:
|
||||
ctx->ex_arg = arg2;
|
||||
break;
|
||||
|
||||
case BIO_C_GET_EX_ARG:
|
||||
*(void **)arg2 = ctx->ex_arg;
|
||||
break;
|
||||
|
||||
case BIO_CTRL_FLUSH:
|
||||
if (next == NULL)
|
||||
return 0;
|
||||
|
||||
/* Call post function if possible */
|
||||
if (ctx->state == ASN1_STATE_HEADER) {
|
||||
if (!asn1_bio_setup_ex(b, ctx, ctx->suffix,
|
||||
ASN1_STATE_POST_COPY, ASN1_STATE_DONE))
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (ctx->state == ASN1_STATE_POST_COPY) {
|
||||
ret = asn1_bio_flush_ex(b, ctx, ctx->suffix_free,
|
||||
ASN1_STATE_DONE);
|
||||
if (ret <= 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (ctx->state == ASN1_STATE_DONE)
|
||||
return BIO_ctrl(next, cmd, arg1, arg2);
|
||||
else {
|
||||
BIO_clear_retry_flags(b);
|
||||
return 0;
|
||||
}
|
||||
|
||||
default:
|
||||
if (next == NULL)
|
||||
return 0;
|
||||
return BIO_ctrl(next, cmd, arg1, arg2);
|
||||
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int asn1_bio_set_ex(BIO *b, int cmd,
|
||||
asn1_ps_func *ex_func, asn1_ps_func *ex_free_func)
|
||||
{
|
||||
BIO_ASN1_EX_FUNCS extmp;
|
||||
extmp.ex_func = ex_func;
|
||||
extmp.ex_free_func = ex_free_func;
|
||||
return BIO_ctrl(b, cmd, 0, &extmp);
|
||||
}
|
||||
|
||||
static int asn1_bio_get_ex(BIO *b, int cmd,
|
||||
asn1_ps_func **ex_func,
|
||||
asn1_ps_func **ex_free_func)
|
||||
{
|
||||
BIO_ASN1_EX_FUNCS extmp;
|
||||
int ret;
|
||||
ret = BIO_ctrl(b, cmd, 0, &extmp);
|
||||
if (ret > 0) {
|
||||
*ex_func = extmp.ex_func;
|
||||
*ex_free_func = extmp.ex_free_func;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int BIO_asn1_set_prefix(BIO *b, asn1_ps_func *prefix,
|
||||
asn1_ps_func *prefix_free)
|
||||
{
|
||||
return asn1_bio_set_ex(b, BIO_C_SET_PREFIX, prefix, prefix_free);
|
||||
}
|
||||
|
||||
int BIO_asn1_get_prefix(BIO *b, asn1_ps_func **pprefix,
|
||||
asn1_ps_func **pprefix_free)
|
||||
{
|
||||
return asn1_bio_get_ex(b, BIO_C_GET_PREFIX, pprefix, pprefix_free);
|
||||
}
|
||||
|
||||
int BIO_asn1_set_suffix(BIO *b, asn1_ps_func *suffix,
|
||||
asn1_ps_func *suffix_free)
|
||||
{
|
||||
return asn1_bio_set_ex(b, BIO_C_SET_SUFFIX, suffix, suffix_free);
|
||||
}
|
||||
|
||||
int BIO_asn1_get_suffix(BIO *b, asn1_ps_func **psuffix,
|
||||
asn1_ps_func **psuffix_free)
|
||||
{
|
||||
return asn1_bio_get_ex(b, BIO_C_GET_SUFFIX, psuffix, psuffix_free);
|
||||
}
|
||||
201
crypto/asn1/bio_ndef.c
Normal file
201
crypto/asn1/bio_ndef.c
Normal file
@@ -0,0 +1,201 @@
|
||||
/*
|
||||
* Copyright 2008-2018 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#include <openssl/asn1.h>
|
||||
#include <openssl/asn1t.h>
|
||||
#include <openssl/bio.h>
|
||||
#include <openssl/err.h>
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
/* Experimental NDEF ASN1 BIO support routines */
|
||||
|
||||
/*
|
||||
* The usage is quite simple, initialize an ASN1 structure, get a BIO from it
|
||||
* then any data written through the BIO will end up translated to
|
||||
* appropriate format on the fly. The data is streamed out and does *not*
|
||||
* need to be all held in memory at once. When the BIO is flushed the output
|
||||
* is finalized and any signatures etc written out. The BIO is a 'proper'
|
||||
* BIO and can handle non blocking I/O correctly. The usage is simple. The
|
||||
* implementation is *not*...
|
||||
*/
|
||||
|
||||
/* BIO support data stored in the ASN1 BIO ex_arg */
|
||||
|
||||
typedef struct ndef_aux_st {
|
||||
/* ASN1 structure this BIO refers to */
|
||||
ASN1_VALUE *val;
|
||||
const ASN1_ITEM *it;
|
||||
/* Top of the BIO chain */
|
||||
BIO *ndef_bio;
|
||||
/* Output BIO */
|
||||
BIO *out;
|
||||
/* Boundary where content is inserted */
|
||||
unsigned char **boundary;
|
||||
/* DER buffer start */
|
||||
unsigned char *derbuf;
|
||||
} NDEF_SUPPORT;
|
||||
|
||||
static int ndef_prefix(BIO *b, unsigned char **pbuf, int *plen, void *parg);
|
||||
static int ndef_prefix_free(BIO *b, unsigned char **pbuf, int *plen,
|
||||
void *parg);
|
||||
static int ndef_suffix(BIO *b, unsigned char **pbuf, int *plen, void *parg);
|
||||
static int ndef_suffix_free(BIO *b, unsigned char **pbuf, int *plen,
|
||||
void *parg);
|
||||
|
||||
BIO *BIO_new_NDEF(BIO *out, ASN1_VALUE *val, const ASN1_ITEM *it)
|
||||
{
|
||||
NDEF_SUPPORT *ndef_aux = NULL;
|
||||
BIO *asn_bio = NULL;
|
||||
const ASN1_AUX *aux = it->funcs;
|
||||
ASN1_STREAM_ARG sarg;
|
||||
|
||||
if (!aux || !aux->asn1_cb) {
|
||||
ASN1err(ASN1_F_BIO_NEW_NDEF, ASN1_R_STREAMING_NOT_SUPPORTED);
|
||||
return NULL;
|
||||
}
|
||||
ndef_aux = OPENSSL_zalloc(sizeof(*ndef_aux));
|
||||
asn_bio = BIO_new(BIO_f_asn1());
|
||||
if (ndef_aux == NULL || asn_bio == NULL)
|
||||
goto err;
|
||||
|
||||
/* ASN1 bio needs to be next to output BIO */
|
||||
out = BIO_push(asn_bio, out);
|
||||
if (out == NULL)
|
||||
goto err;
|
||||
|
||||
BIO_asn1_set_prefix(asn_bio, ndef_prefix, ndef_prefix_free);
|
||||
BIO_asn1_set_suffix(asn_bio, ndef_suffix, ndef_suffix_free);
|
||||
|
||||
/*
|
||||
* Now let callback prepends any digest, cipher etc BIOs ASN1 structure
|
||||
* needs.
|
||||
*/
|
||||
|
||||
sarg.out = out;
|
||||
sarg.ndef_bio = NULL;
|
||||
sarg.boundary = NULL;
|
||||
|
||||
if (aux->asn1_cb(ASN1_OP_STREAM_PRE, &val, it, &sarg) <= 0)
|
||||
goto err;
|
||||
|
||||
ndef_aux->val = val;
|
||||
ndef_aux->it = it;
|
||||
ndef_aux->ndef_bio = sarg.ndef_bio;
|
||||
ndef_aux->boundary = sarg.boundary;
|
||||
ndef_aux->out = out;
|
||||
|
||||
BIO_ctrl(asn_bio, BIO_C_SET_EX_ARG, 0, ndef_aux);
|
||||
|
||||
return sarg.ndef_bio;
|
||||
|
||||
err:
|
||||
BIO_free(asn_bio);
|
||||
OPENSSL_free(ndef_aux);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int ndef_prefix(BIO *b, unsigned char **pbuf, int *plen, void *parg)
|
||||
{
|
||||
NDEF_SUPPORT *ndef_aux;
|
||||
unsigned char *p;
|
||||
int derlen;
|
||||
|
||||
if (!parg)
|
||||
return 0;
|
||||
|
||||
ndef_aux = *(NDEF_SUPPORT **)parg;
|
||||
|
||||
derlen = ASN1_item_ndef_i2d(ndef_aux->val, NULL, ndef_aux->it);
|
||||
if ((p = OPENSSL_malloc(derlen)) == NULL) {
|
||||
ASN1err(ASN1_F_NDEF_PREFIX, ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
ndef_aux->derbuf = p;
|
||||
*pbuf = p;
|
||||
derlen = ASN1_item_ndef_i2d(ndef_aux->val, &p, ndef_aux->it);
|
||||
|
||||
if (!*ndef_aux->boundary)
|
||||
return 0;
|
||||
|
||||
*plen = *ndef_aux->boundary - *pbuf;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int ndef_prefix_free(BIO *b, unsigned char **pbuf, int *plen,
|
||||
void *parg)
|
||||
{
|
||||
NDEF_SUPPORT *ndef_aux;
|
||||
|
||||
if (!parg)
|
||||
return 0;
|
||||
|
||||
ndef_aux = *(NDEF_SUPPORT **)parg;
|
||||
|
||||
OPENSSL_free(ndef_aux->derbuf);
|
||||
|
||||
ndef_aux->derbuf = NULL;
|
||||
*pbuf = NULL;
|
||||
*plen = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int ndef_suffix_free(BIO *b, unsigned char **pbuf, int *plen,
|
||||
void *parg)
|
||||
{
|
||||
NDEF_SUPPORT **pndef_aux = (NDEF_SUPPORT **)parg;
|
||||
if (!ndef_prefix_free(b, pbuf, plen, parg))
|
||||
return 0;
|
||||
OPENSSL_free(*pndef_aux);
|
||||
*pndef_aux = NULL;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int ndef_suffix(BIO *b, unsigned char **pbuf, int *plen, void *parg)
|
||||
{
|
||||
NDEF_SUPPORT *ndef_aux;
|
||||
unsigned char *p;
|
||||
int derlen;
|
||||
const ASN1_AUX *aux;
|
||||
ASN1_STREAM_ARG sarg;
|
||||
|
||||
if (!parg)
|
||||
return 0;
|
||||
|
||||
ndef_aux = *(NDEF_SUPPORT **)parg;
|
||||
|
||||
aux = ndef_aux->it->funcs;
|
||||
|
||||
/* Finalize structures */
|
||||
sarg.ndef_bio = ndef_aux->ndef_bio;
|
||||
sarg.out = ndef_aux->out;
|
||||
sarg.boundary = ndef_aux->boundary;
|
||||
if (aux->asn1_cb(ASN1_OP_STREAM_POST,
|
||||
&ndef_aux->val, ndef_aux->it, &sarg) <= 0)
|
||||
return 0;
|
||||
|
||||
derlen = ASN1_item_ndef_i2d(ndef_aux->val, NULL, ndef_aux->it);
|
||||
if ((p = OPENSSL_malloc(derlen)) == NULL) {
|
||||
ASN1err(ASN1_F_NDEF_SUFFIX, ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
ndef_aux->derbuf = p;
|
||||
*pbuf = p;
|
||||
derlen = ASN1_item_ndef_i2d(ndef_aux->val, &p, ndef_aux->it);
|
||||
|
||||
if (!*ndef_aux->boundary)
|
||||
return 0;
|
||||
*pbuf = *ndef_aux->boundary;
|
||||
*plen = derlen - (*ndef_aux->boundary - ndef_aux->derbuf);
|
||||
|
||||
return 1;
|
||||
}
|
||||
16
crypto/asn1/build.info
Normal file
16
crypto/asn1/build.info
Normal file
@@ -0,0 +1,16 @@
|
||||
LIBS=../../libcrypto
|
||||
SOURCE[../../libcrypto]=\
|
||||
a_object.c a_bitstr.c a_utctm.c a_gentm.c a_time.c a_int.c a_octet.c \
|
||||
a_print.c a_type.c a_dup.c a_d2i_fp.c a_i2d_fp.c \
|
||||
a_utf8.c a_sign.c a_digest.c a_verify.c a_mbstr.c a_strex.c \
|
||||
x_algor.c x_val.c x_sig.c x_bignum.c \
|
||||
x_long.c x_int64.c x_info.c x_spki.c nsseq.c \
|
||||
d2i_pu.c d2i_pr.c i2d_pu.c i2d_pr.c\
|
||||
t_pkey.c t_spki.c t_bitst.c \
|
||||
tasn_new.c tasn_fre.c tasn_enc.c tasn_dec.c tasn_utl.c tasn_typ.c \
|
||||
tasn_prn.c tasn_scn.c ameth_lib.c \
|
||||
f_int.c f_string.c n_pkey.c \
|
||||
x_pkey.c bio_asn1.c bio_ndef.c asn_mime.c \
|
||||
asn1_gen.c asn1_par.c asn1_lib.c asn1_err.c a_strnid.c \
|
||||
evp_asn1.c asn_pack.c p5_pbe.c p5_pbev2.c p5_scrypt.c p8_pkey.c \
|
||||
asn_moid.c asn_mstbl.c asn1_item_list.c
|
||||
34
crypto/asn1/charmap.h
Normal file
34
crypto/asn1/charmap.h
Normal file
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* WARNING: do not edit!
|
||||
* Generated by crypto/asn1/charmap.pl
|
||||
*
|
||||
* Copyright 2000-2018 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#define CHARTYPE_HOST_ANY 4096
|
||||
#define CHARTYPE_HOST_DOT 8192
|
||||
#define CHARTYPE_HOST_HYPHEN 16384
|
||||
#define CHARTYPE_HOST_WILD 32768
|
||||
|
||||
/*
|
||||
* Mask of various character properties
|
||||
*/
|
||||
|
||||
static const unsigned short char_type[] = {
|
||||
1026, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
|
||||
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
|
||||
2, 2, 2, 2, 2, 2, 2, 2, 120, 0, 1, 40,
|
||||
0, 0, 0, 16, 1040, 1040, 33792, 25, 25, 16400, 8208, 16,
|
||||
4112, 4112, 4112, 4112, 4112, 4112, 4112, 4112, 4112, 4112, 16, 9,
|
||||
9, 16, 9, 16, 0, 4112, 4112, 4112, 4112, 4112, 4112, 4112,
|
||||
4112, 4112, 4112, 4112, 4112, 4112, 4112, 4112, 4112, 4112, 4112, 4112,
|
||||
4112, 4112, 4112, 4112, 4112, 4112, 4112, 0, 1025, 0, 0, 0,
|
||||
0, 4112, 4112, 4112, 4112, 4112, 4112, 4112, 4112, 4112, 4112, 4112,
|
||||
4112, 4112, 4112, 4112, 4112, 4112, 4112, 4112, 4112, 4112, 4112, 4112,
|
||||
4112, 4112, 4112, 0, 0, 0, 0, 2
|
||||
};
|
||||
119
crypto/asn1/charmap.pl
Normal file
119
crypto/asn1/charmap.pl
Normal file
@@ -0,0 +1,119 @@
|
||||
#! /usr/bin/env perl
|
||||
# Copyright 2000-2018 The OpenSSL Project Authors. All Rights Reserved.
|
||||
#
|
||||
# Licensed under the OpenSSL license (the "License"). You may not use
|
||||
# this file except in compliance with the License. You can obtain a copy
|
||||
# in the file LICENSE in the source distribution or at
|
||||
# https://www.openssl.org/source/license.html
|
||||
|
||||
use strict;
|
||||
|
||||
my ($i, @arr);
|
||||
|
||||
# Set up an array with the type of ASCII characters
|
||||
# Each set bit represents a character property.
|
||||
|
||||
# RFC2253 character properties
|
||||
my $RFC2253_ESC = 1; # Character escaped with \
|
||||
my $ESC_CTRL = 2; # Escaped control character
|
||||
# These are used with RFC1779 quoting using "
|
||||
my $NOESC_QUOTE = 8; # Not escaped if quoted
|
||||
my $PSTRING_CHAR = 0x10; # Valid PrintableString character
|
||||
my $RFC2253_FIRST_ESC = 0x20; # Escaped with \ if first character
|
||||
my $RFC2253_LAST_ESC = 0x40; # Escaped with \ if last character
|
||||
my $RFC2254_ESC = 0x400; # Character escaped \XX
|
||||
my $HOST_ANY = 0x1000; # Valid hostname character anywhere in label
|
||||
my $HOST_DOT = 0x2000; # Dot: hostname label separator
|
||||
my $HOST_HYPHEN = 0x4000; # Hyphen: not valid at start or end.
|
||||
my $HOST_WILD = 0x8000; # Wildcard character
|
||||
|
||||
for($i = 0; $i < 128; $i++) {
|
||||
# Set the RFC2253 escape characters (control)
|
||||
$arr[$i] = 0;
|
||||
if(($i < 32) || ($i > 126)) {
|
||||
$arr[$i] |= $ESC_CTRL;
|
||||
}
|
||||
|
||||
# Some PrintableString characters
|
||||
if( ( ( $i >= ord("a")) && ( $i <= ord("z")) )
|
||||
|| ( ( $i >= ord("A")) && ( $i <= ord("Z")) )
|
||||
|| ( ( $i >= ord("0")) && ( $i <= ord("9")) ) ) {
|
||||
$arr[$i] |= $PSTRING_CHAR | $HOST_ANY;
|
||||
}
|
||||
}
|
||||
|
||||
# Now setup the rest
|
||||
|
||||
# Remaining RFC2253 escaped characters
|
||||
|
||||
$arr[ord(" ")] |= $NOESC_QUOTE | $RFC2253_FIRST_ESC | $RFC2253_LAST_ESC;
|
||||
$arr[ord("#")] |= $NOESC_QUOTE | $RFC2253_FIRST_ESC;
|
||||
|
||||
$arr[ord(",")] |= $NOESC_QUOTE | $RFC2253_ESC;
|
||||
$arr[ord("+")] |= $NOESC_QUOTE | $RFC2253_ESC;
|
||||
$arr[ord("\"")] |= $RFC2253_ESC;
|
||||
$arr[ord("\\")] |= $RFC2253_ESC;
|
||||
$arr[ord("<")] |= $NOESC_QUOTE | $RFC2253_ESC;
|
||||
$arr[ord(">")] |= $NOESC_QUOTE | $RFC2253_ESC;
|
||||
$arr[ord(";")] |= $NOESC_QUOTE | $RFC2253_ESC;
|
||||
|
||||
# Remaining RFC2254 characters
|
||||
|
||||
$arr[0] |= $RFC2254_ESC;
|
||||
$arr[ord("(")] |= $RFC2254_ESC;
|
||||
$arr[ord(")")] |= $RFC2254_ESC;
|
||||
$arr[ord("*")] |= $RFC2254_ESC | $HOST_WILD;
|
||||
$arr[ord("\\")] |= $RFC2254_ESC;
|
||||
|
||||
# Remaining PrintableString characters
|
||||
|
||||
$arr[ord(" ")] |= $PSTRING_CHAR;
|
||||
$arr[ord("'")] |= $PSTRING_CHAR;
|
||||
$arr[ord("(")] |= $PSTRING_CHAR;
|
||||
$arr[ord(")")] |= $PSTRING_CHAR;
|
||||
$arr[ord("+")] |= $PSTRING_CHAR;
|
||||
$arr[ord(",")] |= $PSTRING_CHAR;
|
||||
$arr[ord("-")] |= $PSTRING_CHAR | $HOST_HYPHEN;
|
||||
$arr[ord(".")] |= $PSTRING_CHAR | $HOST_DOT;
|
||||
$arr[ord("/")] |= $PSTRING_CHAR;
|
||||
$arr[ord(":")] |= $PSTRING_CHAR;
|
||||
$arr[ord("=")] |= $PSTRING_CHAR;
|
||||
$arr[ord("?")] |= $PSTRING_CHAR;
|
||||
|
||||
# Now generate the C code
|
||||
|
||||
# Output year depends on the year of the script.
|
||||
my $YEAR = [localtime([stat($0)]->[9])]->[5] + 1900;
|
||||
print <<EOF;
|
||||
/*
|
||||
* WARNING: do not edit!
|
||||
* Generated by crypto/asn1/charmap.pl
|
||||
*
|
||||
* Copyright 2000-$YEAR The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#define CHARTYPE_HOST_ANY $HOST_ANY
|
||||
#define CHARTYPE_HOST_DOT $HOST_DOT
|
||||
#define CHARTYPE_HOST_HYPHEN $HOST_HYPHEN
|
||||
#define CHARTYPE_HOST_WILD $HOST_WILD
|
||||
|
||||
/*
|
||||
* Mask of various character properties
|
||||
*/
|
||||
|
||||
static const unsigned short char_type[] = {
|
||||
EOF
|
||||
|
||||
print " ";
|
||||
for($i = 0; $i < 128; $i++) {
|
||||
print("\n ") if($i && (($i % 12) == 0));
|
||||
printf(" %4d", $arr[$i]);
|
||||
print(",") if ($i != 127);
|
||||
}
|
||||
print("\n};\n");
|
||||
|
||||
125
crypto/asn1/d2i_pr.c
Normal file
125
crypto/asn1/d2i_pr.c
Normal file
@@ -0,0 +1,125 @@
|
||||
/*
|
||||
* Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "internal/cryptlib.h"
|
||||
#include <openssl/bn.h>
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/objects.h>
|
||||
#include <openssl/engine.h>
|
||||
#include <openssl/x509.h>
|
||||
#include <openssl/asn1.h>
|
||||
#include "internal/asn1_int.h"
|
||||
#include "internal/evp_int.h"
|
||||
|
||||
EVP_PKEY *d2i_PrivateKey(int type, EVP_PKEY **a, const unsigned char **pp,
|
||||
long length)
|
||||
{
|
||||
EVP_PKEY *ret;
|
||||
const unsigned char *p = *pp;
|
||||
|
||||
if ((a == NULL) || (*a == NULL)) {
|
||||
if ((ret = EVP_PKEY_new()) == NULL) {
|
||||
ASN1err(ASN1_F_D2I_PRIVATEKEY, ERR_R_EVP_LIB);
|
||||
return NULL;
|
||||
}
|
||||
} else {
|
||||
ret = *a;
|
||||
#ifndef OPENSSL_NO_ENGINE
|
||||
ENGINE_finish(ret->engine);
|
||||
ret->engine = NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
if (!EVP_PKEY_set_type(ret, type)) {
|
||||
ASN1err(ASN1_F_D2I_PRIVATEKEY, ASN1_R_UNKNOWN_PUBLIC_KEY_TYPE);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!ret->ameth->old_priv_decode ||
|
||||
!ret->ameth->old_priv_decode(ret, &p, length)) {
|
||||
if (ret->ameth->priv_decode) {
|
||||
EVP_PKEY *tmp;
|
||||
PKCS8_PRIV_KEY_INFO *p8 = NULL;
|
||||
p8 = d2i_PKCS8_PRIV_KEY_INFO(NULL, &p, length);
|
||||
if (!p8)
|
||||
goto err;
|
||||
tmp = EVP_PKCS82PKEY(p8);
|
||||
PKCS8_PRIV_KEY_INFO_free(p8);
|
||||
if (tmp == NULL)
|
||||
goto err;
|
||||
EVP_PKEY_free(ret);
|
||||
ret = tmp;
|
||||
} else {
|
||||
ASN1err(ASN1_F_D2I_PRIVATEKEY, ERR_R_ASN1_LIB);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
*pp = p;
|
||||
if (a != NULL)
|
||||
(*a) = ret;
|
||||
return ret;
|
||||
err:
|
||||
if (a == NULL || *a != ret)
|
||||
EVP_PKEY_free(ret);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* This works like d2i_PrivateKey() except it automatically works out the
|
||||
* type
|
||||
*/
|
||||
|
||||
EVP_PKEY *d2i_AutoPrivateKey(EVP_PKEY **a, const unsigned char **pp,
|
||||
long length)
|
||||
{
|
||||
STACK_OF(ASN1_TYPE) *inkey;
|
||||
const unsigned char *p;
|
||||
int keytype;
|
||||
p = *pp;
|
||||
/*
|
||||
* Dirty trick: read in the ASN1 data into a STACK_OF(ASN1_TYPE): by
|
||||
* analyzing it we can determine the passed structure: this assumes the
|
||||
* input is surrounded by an ASN1 SEQUENCE.
|
||||
*/
|
||||
inkey = d2i_ASN1_SEQUENCE_ANY(NULL, &p, length);
|
||||
p = *pp;
|
||||
/*
|
||||
* Since we only need to discern "traditional format" RSA and DSA keys we
|
||||
* can just count the elements.
|
||||
*/
|
||||
if (sk_ASN1_TYPE_num(inkey) == 6)
|
||||
keytype = EVP_PKEY_DSA;
|
||||
else if (sk_ASN1_TYPE_num(inkey) == 4)
|
||||
keytype = EVP_PKEY_EC;
|
||||
else if (sk_ASN1_TYPE_num(inkey) == 3) { /* This seems to be PKCS8, not
|
||||
* traditional format */
|
||||
PKCS8_PRIV_KEY_INFO *p8 = d2i_PKCS8_PRIV_KEY_INFO(NULL, &p, length);
|
||||
EVP_PKEY *ret;
|
||||
|
||||
sk_ASN1_TYPE_pop_free(inkey, ASN1_TYPE_free);
|
||||
if (!p8) {
|
||||
ASN1err(ASN1_F_D2I_AUTOPRIVATEKEY,
|
||||
ASN1_R_UNSUPPORTED_PUBLIC_KEY_TYPE);
|
||||
return NULL;
|
||||
}
|
||||
ret = EVP_PKCS82PKEY(p8);
|
||||
PKCS8_PRIV_KEY_INFO_free(p8);
|
||||
if (ret == NULL)
|
||||
return NULL;
|
||||
*pp = p;
|
||||
if (a) {
|
||||
*a = ret;
|
||||
}
|
||||
return ret;
|
||||
} else
|
||||
keytype = EVP_PKEY_RSA;
|
||||
sk_ASN1_TYPE_pop_free(inkey, ASN1_TYPE_free);
|
||||
return d2i_PrivateKey(keytype, a, pp, length);
|
||||
}
|
||||
77
crypto/asn1/d2i_pu.c
Normal file
77
crypto/asn1/d2i_pu.c
Normal file
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "internal/cryptlib.h"
|
||||
#include <openssl/bn.h>
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/objects.h>
|
||||
#include <openssl/asn1.h>
|
||||
#include <openssl/rsa.h>
|
||||
#include <openssl/dsa.h>
|
||||
#include <openssl/ec.h>
|
||||
|
||||
#include "internal/evp_int.h"
|
||||
|
||||
EVP_PKEY *d2i_PublicKey(int type, EVP_PKEY **a, const unsigned char **pp,
|
||||
long length)
|
||||
{
|
||||
EVP_PKEY *ret;
|
||||
|
||||
if ((a == NULL) || (*a == NULL)) {
|
||||
if ((ret = EVP_PKEY_new()) == NULL) {
|
||||
ASN1err(ASN1_F_D2I_PUBLICKEY, ERR_R_EVP_LIB);
|
||||
return NULL;
|
||||
}
|
||||
} else
|
||||
ret = *a;
|
||||
|
||||
if (!EVP_PKEY_set_type(ret, type)) {
|
||||
ASN1err(ASN1_F_D2I_PUBLICKEY, ERR_R_EVP_LIB);
|
||||
goto err;
|
||||
}
|
||||
|
||||
switch (EVP_PKEY_id(ret)) {
|
||||
#ifndef OPENSSL_NO_RSA
|
||||
case EVP_PKEY_RSA:
|
||||
if ((ret->pkey.rsa = d2i_RSAPublicKey(NULL, pp, length)) == NULL) {
|
||||
ASN1err(ASN1_F_D2I_PUBLICKEY, ERR_R_ASN1_LIB);
|
||||
goto err;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
#ifndef OPENSSL_NO_DSA
|
||||
case EVP_PKEY_DSA:
|
||||
/* TMP UGLY CAST */
|
||||
if (!d2i_DSAPublicKey(&ret->pkey.dsa, pp, length)) {
|
||||
ASN1err(ASN1_F_D2I_PUBLICKEY, ERR_R_ASN1_LIB);
|
||||
goto err;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
#ifndef OPENSSL_NO_EC
|
||||
case EVP_PKEY_EC:
|
||||
if (!o2i_ECPublicKey(&ret->pkey.ec, pp, length)) {
|
||||
ASN1err(ASN1_F_D2I_PUBLICKEY, ERR_R_ASN1_LIB);
|
||||
goto err;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
ASN1err(ASN1_F_D2I_PUBLICKEY, ASN1_R_UNKNOWN_PUBLIC_KEY_TYPE);
|
||||
goto err;
|
||||
}
|
||||
if (a != NULL)
|
||||
(*a) = ret;
|
||||
return ret;
|
||||
err:
|
||||
if (a == NULL || *a != ret)
|
||||
EVP_PKEY_free(ret);
|
||||
return NULL;
|
||||
}
|
||||
115
crypto/asn1/evp_asn1.c
Normal file
115
crypto/asn1/evp_asn1.c
Normal file
@@ -0,0 +1,115 @@
|
||||
/*
|
||||
* Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "internal/cryptlib.h"
|
||||
#include <openssl/asn1.h>
|
||||
#include <openssl/asn1t.h>
|
||||
|
||||
int ASN1_TYPE_set_octetstring(ASN1_TYPE *a, unsigned char *data, int len)
|
||||
{
|
||||
ASN1_STRING *os;
|
||||
|
||||
if ((os = ASN1_OCTET_STRING_new()) == NULL)
|
||||
return 0;
|
||||
if (!ASN1_OCTET_STRING_set(os, data, len)) {
|
||||
ASN1_OCTET_STRING_free(os);
|
||||
return 0;
|
||||
}
|
||||
ASN1_TYPE_set(a, V_ASN1_OCTET_STRING, os);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* int max_len: for returned value */
|
||||
int ASN1_TYPE_get_octetstring(const ASN1_TYPE *a, unsigned char *data, int max_len)
|
||||
{
|
||||
int ret, num;
|
||||
const unsigned char *p;
|
||||
|
||||
if ((a->type != V_ASN1_OCTET_STRING) || (a->value.octet_string == NULL)) {
|
||||
ASN1err(ASN1_F_ASN1_TYPE_GET_OCTETSTRING, ASN1_R_DATA_IS_WRONG);
|
||||
return -1;
|
||||
}
|
||||
p = ASN1_STRING_get0_data(a->value.octet_string);
|
||||
ret = ASN1_STRING_length(a->value.octet_string);
|
||||
if (ret < max_len)
|
||||
num = ret;
|
||||
else
|
||||
num = max_len;
|
||||
memcpy(data, p, num);
|
||||
return ret;
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
int32_t num;
|
||||
ASN1_OCTET_STRING *oct;
|
||||
} asn1_int_oct;
|
||||
|
||||
ASN1_SEQUENCE(asn1_int_oct) = {
|
||||
ASN1_EMBED(asn1_int_oct, num, INT32),
|
||||
ASN1_SIMPLE(asn1_int_oct, oct, ASN1_OCTET_STRING)
|
||||
} static_ASN1_SEQUENCE_END(asn1_int_oct)
|
||||
|
||||
DECLARE_ASN1_ITEM(asn1_int_oct)
|
||||
|
||||
int ASN1_TYPE_set_int_octetstring(ASN1_TYPE *a, long num, unsigned char *data,
|
||||
int len)
|
||||
{
|
||||
asn1_int_oct atmp;
|
||||
ASN1_OCTET_STRING oct;
|
||||
|
||||
atmp.num = num;
|
||||
atmp.oct = &oct;
|
||||
oct.data = data;
|
||||
oct.type = V_ASN1_OCTET_STRING;
|
||||
oct.length = len;
|
||||
oct.flags = 0;
|
||||
|
||||
if (ASN1_TYPE_pack_sequence(ASN1_ITEM_rptr(asn1_int_oct), &atmp, &a))
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* we return the actual length...
|
||||
*/
|
||||
/* int max_len: for returned value */
|
||||
int ASN1_TYPE_get_int_octetstring(const ASN1_TYPE *a, long *num,
|
||||
unsigned char *data, int max_len)
|
||||
{
|
||||
asn1_int_oct *atmp = NULL;
|
||||
int ret = -1, n;
|
||||
|
||||
if ((a->type != V_ASN1_SEQUENCE) || (a->value.sequence == NULL)) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
atmp = ASN1_TYPE_unpack_sequence(ASN1_ITEM_rptr(asn1_int_oct), a);
|
||||
|
||||
if (atmp == NULL)
|
||||
goto err;
|
||||
|
||||
if (num != NULL)
|
||||
*num = atmp->num;
|
||||
|
||||
ret = ASN1_STRING_length(atmp->oct);
|
||||
if (max_len > ret)
|
||||
n = ret;
|
||||
else
|
||||
n = max_len;
|
||||
|
||||
if (data != NULL)
|
||||
memcpy(data, ASN1_STRING_get0_data(atmp->oct), n);
|
||||
if (ret == -1) {
|
||||
err:
|
||||
ASN1err(ASN1_F_ASN1_TYPE_GET_INT_OCTETSTRING, ASN1_R_DATA_IS_WRONG);
|
||||
}
|
||||
M_ASN1_free_of(atmp, asn1_int_oct);
|
||||
return ret;
|
||||
}
|
||||
156
crypto/asn1/f_int.c
Normal file
156
crypto/asn1/f_int.c
Normal file
@@ -0,0 +1,156 @@
|
||||
/*
|
||||
* Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "internal/ctype.h"
|
||||
#include "internal/cryptlib.h"
|
||||
#include <openssl/buffer.h>
|
||||
#include <openssl/asn1.h>
|
||||
|
||||
int i2a_ASN1_INTEGER(BIO *bp, const ASN1_INTEGER *a)
|
||||
{
|
||||
int i, n = 0;
|
||||
static const char *h = "0123456789ABCDEF";
|
||||
char buf[2];
|
||||
|
||||
if (a == NULL)
|
||||
return 0;
|
||||
|
||||
if (a->type & V_ASN1_NEG) {
|
||||
if (BIO_write(bp, "-", 1) != 1)
|
||||
goto err;
|
||||
n = 1;
|
||||
}
|
||||
|
||||
if (a->length == 0) {
|
||||
if (BIO_write(bp, "00", 2) != 2)
|
||||
goto err;
|
||||
n += 2;
|
||||
} else {
|
||||
for (i = 0; i < a->length; i++) {
|
||||
if ((i != 0) && (i % 35 == 0)) {
|
||||
if (BIO_write(bp, "\\\n", 2) != 2)
|
||||
goto err;
|
||||
n += 2;
|
||||
}
|
||||
buf[0] = h[((unsigned char)a->data[i] >> 4) & 0x0f];
|
||||
buf[1] = h[((unsigned char)a->data[i]) & 0x0f];
|
||||
if (BIO_write(bp, buf, 2) != 2)
|
||||
goto err;
|
||||
n += 2;
|
||||
}
|
||||
}
|
||||
return n;
|
||||
err:
|
||||
return -1;
|
||||
}
|
||||
|
||||
int a2i_ASN1_INTEGER(BIO *bp, ASN1_INTEGER *bs, char *buf, int size)
|
||||
{
|
||||
int i, j, k, m, n, again, bufsize;
|
||||
unsigned char *s = NULL, *sp;
|
||||
unsigned char *bufp;
|
||||
int num = 0, slen = 0, first = 1;
|
||||
|
||||
bs->type = V_ASN1_INTEGER;
|
||||
|
||||
bufsize = BIO_gets(bp, buf, size);
|
||||
for (;;) {
|
||||
if (bufsize < 1)
|
||||
goto err;
|
||||
i = bufsize;
|
||||
if (buf[i - 1] == '\n')
|
||||
buf[--i] = '\0';
|
||||
if (i == 0)
|
||||
goto err;
|
||||
if (buf[i - 1] == '\r')
|
||||
buf[--i] = '\0';
|
||||
if (i == 0)
|
||||
goto err;
|
||||
again = (buf[i - 1] == '\\');
|
||||
|
||||
for (j = 0; j < i; j++) {
|
||||
if (!ossl_isxdigit(buf[j]))
|
||||
{
|
||||
i = j;
|
||||
break;
|
||||
}
|
||||
}
|
||||
buf[i] = '\0';
|
||||
/*
|
||||
* We have now cleared all the crap off the end of the line
|
||||
*/
|
||||
if (i < 2)
|
||||
goto err;
|
||||
|
||||
bufp = (unsigned char *)buf;
|
||||
if (first) {
|
||||
first = 0;
|
||||
if ((bufp[0] == '0') && (bufp[1] == '0')) {
|
||||
bufp += 2;
|
||||
i -= 2;
|
||||
}
|
||||
}
|
||||
k = 0;
|
||||
i -= again;
|
||||
if (i % 2 != 0) {
|
||||
ASN1err(ASN1_F_A2I_ASN1_INTEGER, ASN1_R_ODD_NUMBER_OF_CHARS);
|
||||
OPENSSL_free(s);
|
||||
return 0;
|
||||
}
|
||||
i /= 2;
|
||||
if (num + i > slen) {
|
||||
sp = OPENSSL_clear_realloc(s, slen, num + i * 2);
|
||||
if (sp == NULL) {
|
||||
ASN1err(ASN1_F_A2I_ASN1_INTEGER, ERR_R_MALLOC_FAILURE);
|
||||
OPENSSL_free(s);
|
||||
return 0;
|
||||
}
|
||||
s = sp;
|
||||
slen = num + i * 2;
|
||||
}
|
||||
for (j = 0; j < i; j++, k += 2) {
|
||||
for (n = 0; n < 2; n++) {
|
||||
m = OPENSSL_hexchar2int(bufp[k + n]);
|
||||
if (m < 0) {
|
||||
ASN1err(ASN1_F_A2I_ASN1_INTEGER,
|
||||
ASN1_R_NON_HEX_CHARACTERS);
|
||||
goto err;
|
||||
}
|
||||
s[num + j] <<= 4;
|
||||
s[num + j] |= m;
|
||||
}
|
||||
}
|
||||
num += i;
|
||||
if (again)
|
||||
bufsize = BIO_gets(bp, buf, size);
|
||||
else
|
||||
break;
|
||||
}
|
||||
bs->length = num;
|
||||
bs->data = s;
|
||||
return 1;
|
||||
err:
|
||||
ASN1err(ASN1_F_A2I_ASN1_INTEGER, ASN1_R_SHORT_LINE);
|
||||
OPENSSL_free(s);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int i2a_ASN1_ENUMERATED(BIO *bp, const ASN1_ENUMERATED *a)
|
||||
{
|
||||
return i2a_ASN1_INTEGER(bp, a);
|
||||
}
|
||||
|
||||
int a2i_ASN1_ENUMERATED(BIO *bp, ASN1_ENUMERATED *bs, char *buf, int size)
|
||||
{
|
||||
int rv = a2i_ASN1_INTEGER(bp, bs, buf, size);
|
||||
if (rv == 1)
|
||||
bs->type = V_ASN1_INTEGER | (bs->type & V_ASN1_NEG);
|
||||
return rv;
|
||||
}
|
||||
136
crypto/asn1/f_string.c
Normal file
136
crypto/asn1/f_string.c
Normal file
@@ -0,0 +1,136 @@
|
||||
/*
|
||||
* Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "internal/ctype.h"
|
||||
#include "internal/cryptlib.h"
|
||||
#include <openssl/buffer.h>
|
||||
#include <openssl/asn1.h>
|
||||
|
||||
int i2a_ASN1_STRING(BIO *bp, const ASN1_STRING *a, int type)
|
||||
{
|
||||
int i, n = 0;
|
||||
static const char *h = "0123456789ABCDEF";
|
||||
char buf[2];
|
||||
|
||||
if (a == NULL)
|
||||
return 0;
|
||||
|
||||
if (a->length == 0) {
|
||||
if (BIO_write(bp, "0", 1) != 1)
|
||||
goto err;
|
||||
n = 1;
|
||||
} else {
|
||||
for (i = 0; i < a->length; i++) {
|
||||
if ((i != 0) && (i % 35 == 0)) {
|
||||
if (BIO_write(bp, "\\\n", 2) != 2)
|
||||
goto err;
|
||||
n += 2;
|
||||
}
|
||||
buf[0] = h[((unsigned char)a->data[i] >> 4) & 0x0f];
|
||||
buf[1] = h[((unsigned char)a->data[i]) & 0x0f];
|
||||
if (BIO_write(bp, buf, 2) != 2)
|
||||
goto err;
|
||||
n += 2;
|
||||
}
|
||||
}
|
||||
return n;
|
||||
err:
|
||||
return -1;
|
||||
}
|
||||
|
||||
int a2i_ASN1_STRING(BIO *bp, ASN1_STRING *bs, char *buf, int size)
|
||||
{
|
||||
int i, j, k, m, n, again, bufsize;
|
||||
unsigned char *s = NULL, *sp;
|
||||
unsigned char *bufp;
|
||||
int num = 0, slen = 0, first = 1;
|
||||
|
||||
bufsize = BIO_gets(bp, buf, size);
|
||||
for (;;) {
|
||||
if (bufsize < 1) {
|
||||
if (first)
|
||||
break;
|
||||
else
|
||||
goto err;
|
||||
}
|
||||
first = 0;
|
||||
|
||||
i = bufsize;
|
||||
if (buf[i - 1] == '\n')
|
||||
buf[--i] = '\0';
|
||||
if (i == 0)
|
||||
goto err;
|
||||
if (buf[i - 1] == '\r')
|
||||
buf[--i] = '\0';
|
||||
if (i == 0)
|
||||
goto err;
|
||||
again = (buf[i - 1] == '\\');
|
||||
|
||||
for (j = i - 1; j > 0; j--) {
|
||||
if (!ossl_isxdigit(buf[j])) {
|
||||
i = j;
|
||||
break;
|
||||
}
|
||||
}
|
||||
buf[i] = '\0';
|
||||
/*
|
||||
* We have now cleared all the crap off the end of the line
|
||||
*/
|
||||
if (i < 2)
|
||||
goto err;
|
||||
|
||||
bufp = (unsigned char *)buf;
|
||||
|
||||
k = 0;
|
||||
i -= again;
|
||||
if (i % 2 != 0) {
|
||||
ASN1err(ASN1_F_A2I_ASN1_STRING, ASN1_R_ODD_NUMBER_OF_CHARS);
|
||||
OPENSSL_free(s);
|
||||
return 0;
|
||||
}
|
||||
i /= 2;
|
||||
if (num + i > slen) {
|
||||
sp = OPENSSL_realloc(s, (unsigned int)num + i * 2);
|
||||
if (sp == NULL) {
|
||||
ASN1err(ASN1_F_A2I_ASN1_STRING, ERR_R_MALLOC_FAILURE);
|
||||
OPENSSL_free(s);
|
||||
return 0;
|
||||
}
|
||||
s = sp;
|
||||
slen = num + i * 2;
|
||||
}
|
||||
for (j = 0; j < i; j++, k += 2) {
|
||||
for (n = 0; n < 2; n++) {
|
||||
m = OPENSSL_hexchar2int(bufp[k + n]);
|
||||
if (m < 0) {
|
||||
ASN1err(ASN1_F_A2I_ASN1_STRING,
|
||||
ASN1_R_NON_HEX_CHARACTERS);
|
||||
OPENSSL_free(s);
|
||||
return 0;
|
||||
}
|
||||
s[num + j] <<= 4;
|
||||
s[num + j] |= m;
|
||||
}
|
||||
}
|
||||
num += i;
|
||||
if (again)
|
||||
bufsize = BIO_gets(bp, buf, size);
|
||||
else
|
||||
break;
|
||||
}
|
||||
bs->length = num;
|
||||
bs->data = s;
|
||||
return 1;
|
||||
|
||||
err:
|
||||
ASN1err(ASN1_F_A2I_ASN1_STRING, ASN1_R_SHORT_LINE);
|
||||
OPENSSL_free(s);
|
||||
return 0;
|
||||
}
|
||||
33
crypto/asn1/i2d_pr.c
Normal file
33
crypto/asn1/i2d_pr.c
Normal file
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "internal/cryptlib.h"
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/x509.h>
|
||||
#include "internal/asn1_int.h"
|
||||
#include "internal/evp_int.h"
|
||||
|
||||
int i2d_PrivateKey(EVP_PKEY *a, unsigned char **pp)
|
||||
{
|
||||
if (a->ameth && a->ameth->old_priv_encode) {
|
||||
return a->ameth->old_priv_encode(a, pp);
|
||||
}
|
||||
if (a->ameth && a->ameth->priv_encode) {
|
||||
PKCS8_PRIV_KEY_INFO *p8 = EVP_PKEY2PKCS8(a);
|
||||
int ret = 0;
|
||||
if (p8 != NULL) {
|
||||
ret = i2d_PKCS8_PRIV_KEY_INFO(p8, pp);
|
||||
PKCS8_PRIV_KEY_INFO_free(p8);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
ASN1err(ASN1_F_I2D_PRIVATEKEY, ASN1_R_UNSUPPORTED_PUBLIC_KEY_TYPE);
|
||||
return -1;
|
||||
}
|
||||
38
crypto/asn1/i2d_pu.c
Normal file
38
crypto/asn1/i2d_pu.c
Normal file
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "internal/cryptlib.h"
|
||||
#include <openssl/bn.h>
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/objects.h>
|
||||
#include <openssl/rsa.h>
|
||||
#include <openssl/dsa.h>
|
||||
#include <openssl/ec.h>
|
||||
|
||||
int i2d_PublicKey(EVP_PKEY *a, unsigned char **pp)
|
||||
{
|
||||
switch (EVP_PKEY_id(a)) {
|
||||
#ifndef OPENSSL_NO_RSA
|
||||
case EVP_PKEY_RSA:
|
||||
return i2d_RSAPublicKey(EVP_PKEY_get0_RSA(a), pp);
|
||||
#endif
|
||||
#ifndef OPENSSL_NO_DSA
|
||||
case EVP_PKEY_DSA:
|
||||
return i2d_DSAPublicKey(EVP_PKEY_get0_DSA(a), pp);
|
||||
#endif
|
||||
#ifndef OPENSSL_NO_EC
|
||||
case EVP_PKEY_EC:
|
||||
return i2o_ECPublicKey(EVP_PKEY_get0_EC_KEY(a), pp);
|
||||
#endif
|
||||
default:
|
||||
ASN1err(ASN1_F_I2D_PUBLICKEY, ASN1_R_UNSUPPORTED_PUBLIC_KEY_TYPE);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
62
crypto/asn1/n_pkey.c
Normal file
62
crypto/asn1/n_pkey.c
Normal file
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#include "openssl/opensslconf.h"
|
||||
#ifdef OPENSSL_NO_RSA
|
||||
NON_EMPTY_TRANSLATION_UNIT
|
||||
#else
|
||||
|
||||
# include "internal/cryptlib.h"
|
||||
# include <stdio.h>
|
||||
# include <openssl/rsa.h>
|
||||
# include <openssl/objects.h>
|
||||
# include <openssl/asn1t.h>
|
||||
# include <openssl/evp.h>
|
||||
# include <openssl/x509.h>
|
||||
|
||||
# ifndef OPENSSL_NO_RC4
|
||||
|
||||
typedef struct netscape_pkey_st {
|
||||
int32_t version;
|
||||
X509_ALGOR *algor;
|
||||
ASN1_OCTET_STRING *private_key;
|
||||
} NETSCAPE_PKEY;
|
||||
|
||||
typedef struct netscape_encrypted_pkey_st {
|
||||
ASN1_OCTET_STRING *os;
|
||||
/*
|
||||
* This is the same structure as DigestInfo so use it: although this
|
||||
* isn't really anything to do with digests.
|
||||
*/
|
||||
X509_SIG *enckey;
|
||||
} NETSCAPE_ENCRYPTED_PKEY;
|
||||
|
||||
|
||||
ASN1_BROKEN_SEQUENCE(NETSCAPE_ENCRYPTED_PKEY) = {
|
||||
ASN1_SIMPLE(NETSCAPE_ENCRYPTED_PKEY, os, ASN1_OCTET_STRING),
|
||||
ASN1_SIMPLE(NETSCAPE_ENCRYPTED_PKEY, enckey, X509_SIG)
|
||||
} static_ASN1_BROKEN_SEQUENCE_END(NETSCAPE_ENCRYPTED_PKEY)
|
||||
|
||||
DECLARE_ASN1_FUNCTIONS_const(NETSCAPE_ENCRYPTED_PKEY)
|
||||
DECLARE_ASN1_ENCODE_FUNCTIONS_const(NETSCAPE_ENCRYPTED_PKEY,NETSCAPE_ENCRYPTED_PKEY)
|
||||
IMPLEMENT_ASN1_FUNCTIONS_const(NETSCAPE_ENCRYPTED_PKEY)
|
||||
|
||||
ASN1_SEQUENCE(NETSCAPE_PKEY) = {
|
||||
ASN1_EMBED(NETSCAPE_PKEY, version, INT32),
|
||||
ASN1_SIMPLE(NETSCAPE_PKEY, algor, X509_ALGOR),
|
||||
ASN1_SIMPLE(NETSCAPE_PKEY, private_key, ASN1_OCTET_STRING)
|
||||
} static_ASN1_SEQUENCE_END(NETSCAPE_PKEY)
|
||||
|
||||
DECLARE_ASN1_FUNCTIONS_const(NETSCAPE_PKEY)
|
||||
DECLARE_ASN1_ENCODE_FUNCTIONS_const(NETSCAPE_PKEY,NETSCAPE_PKEY)
|
||||
IMPLEMENT_ASN1_FUNCTIONS_const(NETSCAPE_PKEY)
|
||||
|
||||
# endif /* OPENSSL_NO_RC4 */
|
||||
|
||||
#endif
|
||||
34
crypto/asn1/nsseq.c
Normal file
34
crypto/asn1/nsseq.c
Normal file
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <openssl/asn1t.h>
|
||||
#include <openssl/x509.h>
|
||||
#include <openssl/objects.h>
|
||||
|
||||
static int nsseq_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
|
||||
void *exarg)
|
||||
{
|
||||
if (operation == ASN1_OP_NEW_POST) {
|
||||
NETSCAPE_CERT_SEQUENCE *nsseq;
|
||||
nsseq = (NETSCAPE_CERT_SEQUENCE *)*pval;
|
||||
nsseq->type = OBJ_nid2obj(NID_netscape_cert_sequence);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Netscape certificate sequence structure */
|
||||
|
||||
ASN1_SEQUENCE_cb(NETSCAPE_CERT_SEQUENCE, nsseq_cb) = {
|
||||
ASN1_SIMPLE(NETSCAPE_CERT_SEQUENCE, type, ASN1_OBJECT),
|
||||
ASN1_EXP_SEQUENCE_OF_OPT(NETSCAPE_CERT_SEQUENCE, certs, X509, 0)
|
||||
} ASN1_SEQUENCE_END_cb(NETSCAPE_CERT_SEQUENCE, NETSCAPE_CERT_SEQUENCE)
|
||||
|
||||
IMPLEMENT_ASN1_FUNCTIONS(NETSCAPE_CERT_SEQUENCE)
|
||||
96
crypto/asn1/p5_pbe.c
Normal file
96
crypto/asn1/p5_pbe.c
Normal file
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
* Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "internal/cryptlib.h"
|
||||
#include <openssl/asn1t.h>
|
||||
#include <openssl/x509.h>
|
||||
#include <openssl/rand.h>
|
||||
|
||||
/* PKCS#5 password based encryption structure */
|
||||
|
||||
ASN1_SEQUENCE(PBEPARAM) = {
|
||||
ASN1_SIMPLE(PBEPARAM, salt, ASN1_OCTET_STRING),
|
||||
ASN1_SIMPLE(PBEPARAM, iter, ASN1_INTEGER)
|
||||
} ASN1_SEQUENCE_END(PBEPARAM)
|
||||
|
||||
IMPLEMENT_ASN1_FUNCTIONS(PBEPARAM)
|
||||
|
||||
/* Set an algorithm identifier for a PKCS#5 PBE algorithm */
|
||||
|
||||
int PKCS5_pbe_set0_algor(X509_ALGOR *algor, int alg, int iter,
|
||||
const unsigned char *salt, int saltlen)
|
||||
{
|
||||
PBEPARAM *pbe = NULL;
|
||||
ASN1_STRING *pbe_str = NULL;
|
||||
unsigned char *sstr = NULL;
|
||||
|
||||
pbe = PBEPARAM_new();
|
||||
if (pbe == NULL) {
|
||||
ASN1err(ASN1_F_PKCS5_PBE_SET0_ALGOR, ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
if (iter <= 0)
|
||||
iter = PKCS5_DEFAULT_ITER;
|
||||
if (!ASN1_INTEGER_set(pbe->iter, iter)) {
|
||||
ASN1err(ASN1_F_PKCS5_PBE_SET0_ALGOR, ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
if (!saltlen)
|
||||
saltlen = PKCS5_SALT_LEN;
|
||||
|
||||
sstr = OPENSSL_malloc(saltlen);
|
||||
if (sstr == NULL) {
|
||||
ASN1err(ASN1_F_PKCS5_PBE_SET0_ALGOR, ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
if (salt)
|
||||
memcpy(sstr, salt, saltlen);
|
||||
else if (RAND_bytes(sstr, saltlen) <= 0)
|
||||
goto err;
|
||||
|
||||
ASN1_STRING_set0(pbe->salt, sstr, saltlen);
|
||||
sstr = NULL;
|
||||
|
||||
if (!ASN1_item_pack(pbe, ASN1_ITEM_rptr(PBEPARAM), &pbe_str)) {
|
||||
ASN1err(ASN1_F_PKCS5_PBE_SET0_ALGOR, ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
|
||||
PBEPARAM_free(pbe);
|
||||
pbe = NULL;
|
||||
|
||||
if (X509_ALGOR_set0(algor, OBJ_nid2obj(alg), V_ASN1_SEQUENCE, pbe_str))
|
||||
return 1;
|
||||
|
||||
err:
|
||||
OPENSSL_free(sstr);
|
||||
PBEPARAM_free(pbe);
|
||||
ASN1_STRING_free(pbe_str);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Return an algorithm identifier for a PKCS#5 PBE algorithm */
|
||||
|
||||
X509_ALGOR *PKCS5_pbe_set(int alg, int iter,
|
||||
const unsigned char *salt, int saltlen)
|
||||
{
|
||||
X509_ALGOR *ret;
|
||||
ret = X509_ALGOR_new();
|
||||
if (ret == NULL) {
|
||||
ASN1err(ASN1_F_PKCS5_PBE_SET, ERR_R_MALLOC_FAILURE);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (PKCS5_pbe_set0_algor(ret, alg, iter, salt, saltlen))
|
||||
return ret;
|
||||
|
||||
X509_ALGOR_free(ret);
|
||||
return NULL;
|
||||
}
|
||||
221
crypto/asn1/p5_pbev2.c
Normal file
221
crypto/asn1/p5_pbev2.c
Normal file
@@ -0,0 +1,221 @@
|
||||
/*
|
||||
* Copyright 1999-2018 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "internal/cryptlib.h"
|
||||
#include <openssl/asn1t.h>
|
||||
#include <openssl/x509.h>
|
||||
#include <openssl/rand.h>
|
||||
|
||||
/* PKCS#5 v2.0 password based encryption structures */
|
||||
|
||||
ASN1_SEQUENCE(PBE2PARAM) = {
|
||||
ASN1_SIMPLE(PBE2PARAM, keyfunc, X509_ALGOR),
|
||||
ASN1_SIMPLE(PBE2PARAM, encryption, X509_ALGOR)
|
||||
} ASN1_SEQUENCE_END(PBE2PARAM)
|
||||
|
||||
IMPLEMENT_ASN1_FUNCTIONS(PBE2PARAM)
|
||||
|
||||
ASN1_SEQUENCE(PBKDF2PARAM) = {
|
||||
ASN1_SIMPLE(PBKDF2PARAM, salt, ASN1_ANY),
|
||||
ASN1_SIMPLE(PBKDF2PARAM, iter, ASN1_INTEGER),
|
||||
ASN1_OPT(PBKDF2PARAM, keylength, ASN1_INTEGER),
|
||||
ASN1_OPT(PBKDF2PARAM, prf, X509_ALGOR)
|
||||
} ASN1_SEQUENCE_END(PBKDF2PARAM)
|
||||
|
||||
IMPLEMENT_ASN1_FUNCTIONS(PBKDF2PARAM)
|
||||
|
||||
/*
|
||||
* Return an algorithm identifier for a PKCS#5 v2.0 PBE algorithm: yes I know
|
||||
* this is horrible! Extended version to allow application supplied PRF NID
|
||||
* and IV.
|
||||
*/
|
||||
|
||||
X509_ALGOR *PKCS5_pbe2_set_iv(const EVP_CIPHER *cipher, int iter,
|
||||
unsigned char *salt, int saltlen,
|
||||
unsigned char *aiv, int prf_nid)
|
||||
{
|
||||
X509_ALGOR *scheme = NULL, *ret = NULL;
|
||||
int alg_nid, keylen;
|
||||
EVP_CIPHER_CTX *ctx = NULL;
|
||||
unsigned char iv[EVP_MAX_IV_LENGTH];
|
||||
PBE2PARAM *pbe2 = NULL;
|
||||
|
||||
alg_nid = EVP_CIPHER_type(cipher);
|
||||
if (alg_nid == NID_undef) {
|
||||
ASN1err(ASN1_F_PKCS5_PBE2_SET_IV,
|
||||
ASN1_R_CIPHER_HAS_NO_OBJECT_IDENTIFIER);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if ((pbe2 = PBE2PARAM_new()) == NULL)
|
||||
goto merr;
|
||||
|
||||
/* Setup the AlgorithmIdentifier for the encryption scheme */
|
||||
scheme = pbe2->encryption;
|
||||
scheme->algorithm = OBJ_nid2obj(alg_nid);
|
||||
if ((scheme->parameter = ASN1_TYPE_new()) == NULL)
|
||||
goto merr;
|
||||
|
||||
/* Create random IV */
|
||||
if (EVP_CIPHER_iv_length(cipher)) {
|
||||
if (aiv)
|
||||
memcpy(iv, aiv, EVP_CIPHER_iv_length(cipher));
|
||||
else if (RAND_bytes(iv, EVP_CIPHER_iv_length(cipher)) <= 0)
|
||||
goto err;
|
||||
}
|
||||
|
||||
ctx = EVP_CIPHER_CTX_new();
|
||||
if (ctx == NULL)
|
||||
goto merr;
|
||||
|
||||
/* Dummy cipherinit to just setup the IV, and PRF */
|
||||
if (!EVP_CipherInit_ex(ctx, cipher, NULL, NULL, iv, 0))
|
||||
goto err;
|
||||
if (EVP_CIPHER_param_to_asn1(ctx, scheme->parameter) <= 0) {
|
||||
ASN1err(ASN1_F_PKCS5_PBE2_SET_IV, ASN1_R_ERROR_SETTING_CIPHER_PARAMS);
|
||||
goto err;
|
||||
}
|
||||
/*
|
||||
* If prf NID unspecified see if cipher has a preference. An error is OK
|
||||
* here: just means use default PRF.
|
||||
*/
|
||||
if ((prf_nid == -1) &&
|
||||
EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_PBE_PRF_NID, 0, &prf_nid) <= 0) {
|
||||
ERR_clear_error();
|
||||
prf_nid = NID_hmacWithSHA256;
|
||||
}
|
||||
EVP_CIPHER_CTX_free(ctx);
|
||||
ctx = NULL;
|
||||
|
||||
/* If its RC2 then we'd better setup the key length */
|
||||
|
||||
if (alg_nid == NID_rc2_cbc)
|
||||
keylen = EVP_CIPHER_key_length(cipher);
|
||||
else
|
||||
keylen = -1;
|
||||
|
||||
/* Setup keyfunc */
|
||||
|
||||
X509_ALGOR_free(pbe2->keyfunc);
|
||||
|
||||
pbe2->keyfunc = PKCS5_pbkdf2_set(iter, salt, saltlen, prf_nid, keylen);
|
||||
|
||||
if (!pbe2->keyfunc)
|
||||
goto merr;
|
||||
|
||||
/* Now set up top level AlgorithmIdentifier */
|
||||
|
||||
if ((ret = X509_ALGOR_new()) == NULL)
|
||||
goto merr;
|
||||
|
||||
ret->algorithm = OBJ_nid2obj(NID_pbes2);
|
||||
|
||||
/* Encode PBE2PARAM into parameter */
|
||||
|
||||
if (!ASN1_TYPE_pack_sequence(ASN1_ITEM_rptr(PBE2PARAM), pbe2,
|
||||
&ret->parameter))
|
||||
goto merr;
|
||||
|
||||
PBE2PARAM_free(pbe2);
|
||||
pbe2 = NULL;
|
||||
|
||||
return ret;
|
||||
|
||||
merr:
|
||||
ASN1err(ASN1_F_PKCS5_PBE2_SET_IV, ERR_R_MALLOC_FAILURE);
|
||||
|
||||
err:
|
||||
EVP_CIPHER_CTX_free(ctx);
|
||||
PBE2PARAM_free(pbe2);
|
||||
/* Note 'scheme' is freed as part of pbe2 */
|
||||
X509_ALGOR_free(ret);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
X509_ALGOR *PKCS5_pbe2_set(const EVP_CIPHER *cipher, int iter,
|
||||
unsigned char *salt, int saltlen)
|
||||
{
|
||||
return PKCS5_pbe2_set_iv(cipher, iter, salt, saltlen, NULL, -1);
|
||||
}
|
||||
|
||||
X509_ALGOR *PKCS5_pbkdf2_set(int iter, unsigned char *salt, int saltlen,
|
||||
int prf_nid, int keylen)
|
||||
{
|
||||
X509_ALGOR *keyfunc = NULL;
|
||||
PBKDF2PARAM *kdf = NULL;
|
||||
ASN1_OCTET_STRING *osalt = NULL;
|
||||
|
||||
if ((kdf = PBKDF2PARAM_new()) == NULL)
|
||||
goto merr;
|
||||
if ((osalt = ASN1_OCTET_STRING_new()) == NULL)
|
||||
goto merr;
|
||||
|
||||
kdf->salt->value.octet_string = osalt;
|
||||
kdf->salt->type = V_ASN1_OCTET_STRING;
|
||||
|
||||
if (saltlen == 0)
|
||||
saltlen = PKCS5_SALT_LEN;
|
||||
if ((osalt->data = OPENSSL_malloc(saltlen)) == NULL)
|
||||
goto merr;
|
||||
|
||||
osalt->length = saltlen;
|
||||
|
||||
if (salt)
|
||||
memcpy(osalt->data, salt, saltlen);
|
||||
else if (RAND_bytes(osalt->data, saltlen) <= 0)
|
||||
goto merr;
|
||||
|
||||
if (iter <= 0)
|
||||
iter = PKCS5_DEFAULT_ITER;
|
||||
|
||||
if (!ASN1_INTEGER_set(kdf->iter, iter))
|
||||
goto merr;
|
||||
|
||||
/* If have a key len set it up */
|
||||
|
||||
if (keylen > 0) {
|
||||
if ((kdf->keylength = ASN1_INTEGER_new()) == NULL)
|
||||
goto merr;
|
||||
if (!ASN1_INTEGER_set(kdf->keylength, keylen))
|
||||
goto merr;
|
||||
}
|
||||
|
||||
/* prf can stay NULL if we are using hmacWithSHA1 */
|
||||
if (prf_nid > 0 && prf_nid != NID_hmacWithSHA1) {
|
||||
kdf->prf = X509_ALGOR_new();
|
||||
if (kdf->prf == NULL)
|
||||
goto merr;
|
||||
X509_ALGOR_set0(kdf->prf, OBJ_nid2obj(prf_nid), V_ASN1_NULL, NULL);
|
||||
}
|
||||
|
||||
/* Finally setup the keyfunc structure */
|
||||
|
||||
keyfunc = X509_ALGOR_new();
|
||||
if (keyfunc == NULL)
|
||||
goto merr;
|
||||
|
||||
keyfunc->algorithm = OBJ_nid2obj(NID_id_pbkdf2);
|
||||
|
||||
/* Encode PBKDF2PARAM into parameter of pbe2 */
|
||||
|
||||
if (!ASN1_TYPE_pack_sequence(ASN1_ITEM_rptr(PBKDF2PARAM), kdf,
|
||||
&keyfunc->parameter))
|
||||
goto merr;
|
||||
|
||||
PBKDF2PARAM_free(kdf);
|
||||
return keyfunc;
|
||||
|
||||
merr:
|
||||
ASN1err(ASN1_F_PKCS5_PBKDF2_SET, ERR_R_MALLOC_FAILURE);
|
||||
PBKDF2PARAM_free(kdf);
|
||||
X509_ALGOR_free(keyfunc);
|
||||
return NULL;
|
||||
}
|
||||
274
crypto/asn1/p5_scrypt.c
Normal file
274
crypto/asn1/p5_scrypt.c
Normal file
@@ -0,0 +1,274 @@
|
||||
/*
|
||||
* Copyright 2015-2018 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "internal/cryptlib.h"
|
||||
#include <openssl/asn1t.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/x509.h>
|
||||
#include <openssl/rand.h>
|
||||
|
||||
#ifndef OPENSSL_NO_SCRYPT
|
||||
/* PKCS#5 scrypt password based encryption structures */
|
||||
|
||||
ASN1_SEQUENCE(SCRYPT_PARAMS) = {
|
||||
ASN1_SIMPLE(SCRYPT_PARAMS, salt, ASN1_OCTET_STRING),
|
||||
ASN1_SIMPLE(SCRYPT_PARAMS, costParameter, ASN1_INTEGER),
|
||||
ASN1_SIMPLE(SCRYPT_PARAMS, blockSize, ASN1_INTEGER),
|
||||
ASN1_SIMPLE(SCRYPT_PARAMS, parallelizationParameter, ASN1_INTEGER),
|
||||
ASN1_OPT(SCRYPT_PARAMS, keyLength, ASN1_INTEGER),
|
||||
} ASN1_SEQUENCE_END(SCRYPT_PARAMS)
|
||||
|
||||
IMPLEMENT_ASN1_FUNCTIONS(SCRYPT_PARAMS)
|
||||
|
||||
static X509_ALGOR *pkcs5_scrypt_set(const unsigned char *salt, size_t saltlen,
|
||||
size_t keylen, uint64_t N, uint64_t r,
|
||||
uint64_t p);
|
||||
|
||||
/*
|
||||
* Return an algorithm identifier for a PKCS#5 v2.0 PBE algorithm using scrypt
|
||||
*/
|
||||
|
||||
X509_ALGOR *PKCS5_pbe2_set_scrypt(const EVP_CIPHER *cipher,
|
||||
const unsigned char *salt, int saltlen,
|
||||
unsigned char *aiv, uint64_t N, uint64_t r,
|
||||
uint64_t p)
|
||||
{
|
||||
X509_ALGOR *scheme = NULL, *ret = NULL;
|
||||
int alg_nid;
|
||||
size_t keylen = 0;
|
||||
EVP_CIPHER_CTX *ctx = NULL;
|
||||
unsigned char iv[EVP_MAX_IV_LENGTH];
|
||||
PBE2PARAM *pbe2 = NULL;
|
||||
|
||||
if (!cipher) {
|
||||
ASN1err(ASN1_F_PKCS5_PBE2_SET_SCRYPT, ERR_R_PASSED_NULL_PARAMETER);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (EVP_PBE_scrypt(NULL, 0, NULL, 0, N, r, p, 0, NULL, 0) == 0) {
|
||||
ASN1err(ASN1_F_PKCS5_PBE2_SET_SCRYPT,
|
||||
ASN1_R_INVALID_SCRYPT_PARAMETERS);
|
||||
goto err;
|
||||
}
|
||||
|
||||
alg_nid = EVP_CIPHER_type(cipher);
|
||||
if (alg_nid == NID_undef) {
|
||||
ASN1err(ASN1_F_PKCS5_PBE2_SET_SCRYPT,
|
||||
ASN1_R_CIPHER_HAS_NO_OBJECT_IDENTIFIER);
|
||||
goto err;
|
||||
}
|
||||
|
||||
pbe2 = PBE2PARAM_new();
|
||||
if (pbe2 == NULL)
|
||||
goto merr;
|
||||
|
||||
/* Setup the AlgorithmIdentifier for the encryption scheme */
|
||||
scheme = pbe2->encryption;
|
||||
|
||||
scheme->algorithm = OBJ_nid2obj(alg_nid);
|
||||
scheme->parameter = ASN1_TYPE_new();
|
||||
if (scheme->parameter == NULL)
|
||||
goto merr;
|
||||
|
||||
/* Create random IV */
|
||||
if (EVP_CIPHER_iv_length(cipher)) {
|
||||
if (aiv)
|
||||
memcpy(iv, aiv, EVP_CIPHER_iv_length(cipher));
|
||||
else if (RAND_bytes(iv, EVP_CIPHER_iv_length(cipher)) <= 0)
|
||||
goto err;
|
||||
}
|
||||
|
||||
ctx = EVP_CIPHER_CTX_new();
|
||||
if (ctx == NULL)
|
||||
goto merr;
|
||||
|
||||
/* Dummy cipherinit to just setup the IV */
|
||||
if (EVP_CipherInit_ex(ctx, cipher, NULL, NULL, iv, 0) == 0)
|
||||
goto err;
|
||||
if (EVP_CIPHER_param_to_asn1(ctx, scheme->parameter) <= 0) {
|
||||
ASN1err(ASN1_F_PKCS5_PBE2_SET_SCRYPT,
|
||||
ASN1_R_ERROR_SETTING_CIPHER_PARAMS);
|
||||
goto err;
|
||||
}
|
||||
EVP_CIPHER_CTX_free(ctx);
|
||||
ctx = NULL;
|
||||
|
||||
/* If its RC2 then we'd better setup the key length */
|
||||
|
||||
if (alg_nid == NID_rc2_cbc)
|
||||
keylen = EVP_CIPHER_key_length(cipher);
|
||||
|
||||
/* Setup keyfunc */
|
||||
|
||||
X509_ALGOR_free(pbe2->keyfunc);
|
||||
|
||||
pbe2->keyfunc = pkcs5_scrypt_set(salt, saltlen, keylen, N, r, p);
|
||||
|
||||
if (pbe2->keyfunc == NULL)
|
||||
goto merr;
|
||||
|
||||
/* Now set up top level AlgorithmIdentifier */
|
||||
|
||||
ret = X509_ALGOR_new();
|
||||
if (ret == NULL)
|
||||
goto merr;
|
||||
|
||||
ret->algorithm = OBJ_nid2obj(NID_pbes2);
|
||||
|
||||
/* Encode PBE2PARAM into parameter */
|
||||
|
||||
if (ASN1_TYPE_pack_sequence(ASN1_ITEM_rptr(PBE2PARAM), pbe2,
|
||||
&ret->parameter) == NULL)
|
||||
goto merr;
|
||||
|
||||
PBE2PARAM_free(pbe2);
|
||||
pbe2 = NULL;
|
||||
|
||||
return ret;
|
||||
|
||||
merr:
|
||||
ASN1err(ASN1_F_PKCS5_PBE2_SET_SCRYPT, ERR_R_MALLOC_FAILURE);
|
||||
|
||||
err:
|
||||
PBE2PARAM_free(pbe2);
|
||||
X509_ALGOR_free(ret);
|
||||
EVP_CIPHER_CTX_free(ctx);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static X509_ALGOR *pkcs5_scrypt_set(const unsigned char *salt, size_t saltlen,
|
||||
size_t keylen, uint64_t N, uint64_t r,
|
||||
uint64_t p)
|
||||
{
|
||||
X509_ALGOR *keyfunc = NULL;
|
||||
SCRYPT_PARAMS *sparam = SCRYPT_PARAMS_new();
|
||||
|
||||
if (sparam == NULL)
|
||||
goto merr;
|
||||
|
||||
if (!saltlen)
|
||||
saltlen = PKCS5_SALT_LEN;
|
||||
|
||||
/* This will either copy salt or grow the buffer */
|
||||
if (ASN1_STRING_set(sparam->salt, salt, saltlen) == 0)
|
||||
goto merr;
|
||||
|
||||
if (salt == NULL && RAND_bytes(sparam->salt->data, saltlen) <= 0)
|
||||
goto err;
|
||||
|
||||
if (ASN1_INTEGER_set_uint64(sparam->costParameter, N) == 0)
|
||||
goto merr;
|
||||
|
||||
if (ASN1_INTEGER_set_uint64(sparam->blockSize, r) == 0)
|
||||
goto merr;
|
||||
|
||||
if (ASN1_INTEGER_set_uint64(sparam->parallelizationParameter, p) == 0)
|
||||
goto merr;
|
||||
|
||||
/* If have a key len set it up */
|
||||
|
||||
if (keylen > 0) {
|
||||
sparam->keyLength = ASN1_INTEGER_new();
|
||||
if (sparam->keyLength == NULL)
|
||||
goto merr;
|
||||
if (ASN1_INTEGER_set_int64(sparam->keyLength, keylen) == 0)
|
||||
goto merr;
|
||||
}
|
||||
|
||||
/* Finally setup the keyfunc structure */
|
||||
|
||||
keyfunc = X509_ALGOR_new();
|
||||
if (keyfunc == NULL)
|
||||
goto merr;
|
||||
|
||||
keyfunc->algorithm = OBJ_nid2obj(NID_id_scrypt);
|
||||
|
||||
/* Encode SCRYPT_PARAMS into parameter of pbe2 */
|
||||
|
||||
if (ASN1_TYPE_pack_sequence(ASN1_ITEM_rptr(SCRYPT_PARAMS), sparam,
|
||||
&keyfunc->parameter) == NULL)
|
||||
goto merr;
|
||||
|
||||
SCRYPT_PARAMS_free(sparam);
|
||||
return keyfunc;
|
||||
|
||||
merr:
|
||||
ASN1err(ASN1_F_PKCS5_SCRYPT_SET, ERR_R_MALLOC_FAILURE);
|
||||
err:
|
||||
SCRYPT_PARAMS_free(sparam);
|
||||
X509_ALGOR_free(keyfunc);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int PKCS5_v2_scrypt_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass,
|
||||
int passlen, ASN1_TYPE *param,
|
||||
const EVP_CIPHER *c, const EVP_MD *md, int en_de)
|
||||
{
|
||||
unsigned char *salt, key[EVP_MAX_KEY_LENGTH];
|
||||
uint64_t p, r, N;
|
||||
size_t saltlen;
|
||||
size_t keylen = 0;
|
||||
int rv = 0;
|
||||
SCRYPT_PARAMS *sparam = NULL;
|
||||
|
||||
if (EVP_CIPHER_CTX_cipher(ctx) == NULL) {
|
||||
EVPerr(EVP_F_PKCS5_V2_SCRYPT_KEYIVGEN, EVP_R_NO_CIPHER_SET);
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Decode parameter */
|
||||
|
||||
sparam = ASN1_TYPE_unpack_sequence(ASN1_ITEM_rptr(SCRYPT_PARAMS), param);
|
||||
|
||||
if (sparam == NULL) {
|
||||
EVPerr(EVP_F_PKCS5_V2_SCRYPT_KEYIVGEN, EVP_R_DECODE_ERROR);
|
||||
goto err;
|
||||
}
|
||||
|
||||
keylen = EVP_CIPHER_CTX_key_length(ctx);
|
||||
|
||||
/* Now check the parameters of sparam */
|
||||
|
||||
if (sparam->keyLength) {
|
||||
uint64_t spkeylen;
|
||||
if ((ASN1_INTEGER_get_uint64(&spkeylen, sparam->keyLength) == 0)
|
||||
|| (spkeylen != keylen)) {
|
||||
EVPerr(EVP_F_PKCS5_V2_SCRYPT_KEYIVGEN,
|
||||
EVP_R_UNSUPPORTED_KEYLENGTH);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
/* Check all parameters fit in uint64_t and are acceptable to scrypt */
|
||||
if (ASN1_INTEGER_get_uint64(&N, sparam->costParameter) == 0
|
||||
|| ASN1_INTEGER_get_uint64(&r, sparam->blockSize) == 0
|
||||
|| ASN1_INTEGER_get_uint64(&p, sparam->parallelizationParameter) == 0
|
||||
|| EVP_PBE_scrypt(NULL, 0, NULL, 0, N, r, p, 0, NULL, 0) == 0) {
|
||||
EVPerr(EVP_F_PKCS5_V2_SCRYPT_KEYIVGEN,
|
||||
EVP_R_ILLEGAL_SCRYPT_PARAMETERS);
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* it seems that its all OK */
|
||||
|
||||
salt = sparam->salt->data;
|
||||
saltlen = sparam->salt->length;
|
||||
if (EVP_PBE_scrypt(pass, passlen, salt, saltlen, N, r, p, 0, key, keylen)
|
||||
== 0)
|
||||
goto err;
|
||||
rv = EVP_CipherInit_ex(ctx, NULL, NULL, key, NULL, en_de);
|
||||
err:
|
||||
if (keylen)
|
||||
OPENSSL_cleanse(key, keylen);
|
||||
SCRYPT_PARAMS_free(sparam);
|
||||
return rv;
|
||||
}
|
||||
#endif /* OPENSSL_NO_SCRYPT */
|
||||
80
crypto/asn1/p8_pkey.c
Normal file
80
crypto/asn1/p8_pkey.c
Normal file
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "internal/cryptlib.h"
|
||||
#include <openssl/asn1t.h>
|
||||
#include <openssl/x509.h>
|
||||
#include "internal/x509_int.h"
|
||||
|
||||
/* Minor tweak to operation: zero private key data */
|
||||
static int pkey_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
|
||||
void *exarg)
|
||||
{
|
||||
/* Since the structure must still be valid use ASN1_OP_FREE_PRE */
|
||||
if (operation == ASN1_OP_FREE_PRE) {
|
||||
PKCS8_PRIV_KEY_INFO *key = (PKCS8_PRIV_KEY_INFO *)*pval;
|
||||
if (key->pkey)
|
||||
OPENSSL_cleanse(key->pkey->data, key->pkey->length);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
ASN1_SEQUENCE_cb(PKCS8_PRIV_KEY_INFO, pkey_cb) = {
|
||||
ASN1_SIMPLE(PKCS8_PRIV_KEY_INFO, version, ASN1_INTEGER),
|
||||
ASN1_SIMPLE(PKCS8_PRIV_KEY_INFO, pkeyalg, X509_ALGOR),
|
||||
ASN1_SIMPLE(PKCS8_PRIV_KEY_INFO, pkey, ASN1_OCTET_STRING),
|
||||
ASN1_IMP_SET_OF_OPT(PKCS8_PRIV_KEY_INFO, attributes, X509_ATTRIBUTE, 0)
|
||||
} ASN1_SEQUENCE_END_cb(PKCS8_PRIV_KEY_INFO, PKCS8_PRIV_KEY_INFO)
|
||||
|
||||
IMPLEMENT_ASN1_FUNCTIONS(PKCS8_PRIV_KEY_INFO)
|
||||
|
||||
int PKCS8_pkey_set0(PKCS8_PRIV_KEY_INFO *priv, ASN1_OBJECT *aobj,
|
||||
int version,
|
||||
int ptype, void *pval, unsigned char *penc, int penclen)
|
||||
{
|
||||
if (version >= 0) {
|
||||
if (!ASN1_INTEGER_set(priv->version, version))
|
||||
return 0;
|
||||
}
|
||||
if (!X509_ALGOR_set0(priv->pkeyalg, aobj, ptype, pval))
|
||||
return 0;
|
||||
if (penc)
|
||||
ASN1_STRING_set0(priv->pkey, penc, penclen);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int PKCS8_pkey_get0(const ASN1_OBJECT **ppkalg,
|
||||
const unsigned char **pk, int *ppklen,
|
||||
const X509_ALGOR **pa, const PKCS8_PRIV_KEY_INFO *p8)
|
||||
{
|
||||
if (ppkalg)
|
||||
*ppkalg = p8->pkeyalg->algorithm;
|
||||
if (pk) {
|
||||
*pk = ASN1_STRING_get0_data(p8->pkey);
|
||||
*ppklen = ASN1_STRING_length(p8->pkey);
|
||||
}
|
||||
if (pa)
|
||||
*pa = p8->pkeyalg;
|
||||
return 1;
|
||||
}
|
||||
|
||||
const STACK_OF(X509_ATTRIBUTE) *
|
||||
PKCS8_pkey_get0_attrs(const PKCS8_PRIV_KEY_INFO *p8)
|
||||
{
|
||||
return p8->attributes;
|
||||
}
|
||||
|
||||
int PKCS8_pkey_add1_attr_by_NID(PKCS8_PRIV_KEY_INFO *p8, int nid, int type,
|
||||
const unsigned char *bytes, int len)
|
||||
{
|
||||
if (X509at_add1_attr_by_NID(&p8->attributes, nid, type, bytes, len) != NULL)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
61
crypto/asn1/standard_methods.h
Normal file
61
crypto/asn1/standard_methods.h
Normal file
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright 2006-2018 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
/*
|
||||
* This table MUST be kept in ascending order of the NID each method
|
||||
* represents (corresponding to the pkey_id field) as OBJ_bsearch
|
||||
* is used to search it.
|
||||
*/
|
||||
static const EVP_PKEY_ASN1_METHOD *standard_methods[] = {
|
||||
#ifndef OPENSSL_NO_RSA
|
||||
&rsa_asn1_meths[0],
|
||||
&rsa_asn1_meths[1],
|
||||
#endif
|
||||
#ifndef OPENSSL_NO_DH
|
||||
&dh_asn1_meth,
|
||||
#endif
|
||||
#ifndef OPENSSL_NO_DSA
|
||||
&dsa_asn1_meths[0],
|
||||
&dsa_asn1_meths[1],
|
||||
&dsa_asn1_meths[2],
|
||||
&dsa_asn1_meths[3],
|
||||
&dsa_asn1_meths[4],
|
||||
#endif
|
||||
#ifndef OPENSSL_NO_EC
|
||||
&eckey_asn1_meth,
|
||||
#endif
|
||||
&hmac_asn1_meth,
|
||||
#ifndef OPENSSL_NO_CMAC
|
||||
&cmac_asn1_meth,
|
||||
#endif
|
||||
#ifndef OPENSSL_NO_RSA
|
||||
&rsa_pss_asn1_meth,
|
||||
#endif
|
||||
#ifndef OPENSSL_NO_DH
|
||||
&dhx_asn1_meth,
|
||||
#endif
|
||||
#ifndef OPENSSL_NO_EC
|
||||
&ecx25519_asn1_meth,
|
||||
&ecx448_asn1_meth,
|
||||
#endif
|
||||
#ifndef OPENSSL_NO_POLY1305
|
||||
&poly1305_asn1_meth,
|
||||
#endif
|
||||
#ifndef OPENSSL_NO_SIPHASH
|
||||
&siphash_asn1_meth,
|
||||
#endif
|
||||
#ifndef OPENSSL_NO_EC
|
||||
&ed25519_asn1_meth,
|
||||
&ed448_asn1_meth,
|
||||
#endif
|
||||
#ifndef OPENSSL_NO_SM2
|
||||
&sm2_asn1_meth,
|
||||
#endif
|
||||
};
|
||||
|
||||
56
crypto/asn1/t_bitst.c
Normal file
56
crypto/asn1/t_bitst.c
Normal file
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "internal/cryptlib.h"
|
||||
#include <openssl/conf.h>
|
||||
#include <openssl/x509v3.h>
|
||||
|
||||
int ASN1_BIT_STRING_name_print(BIO *out, ASN1_BIT_STRING *bs,
|
||||
BIT_STRING_BITNAME *tbl, int indent)
|
||||
{
|
||||
BIT_STRING_BITNAME *bnam;
|
||||
char first = 1;
|
||||
BIO_printf(out, "%*s", indent, "");
|
||||
for (bnam = tbl; bnam->lname; bnam++) {
|
||||
if (ASN1_BIT_STRING_get_bit(bs, bnam->bitnum)) {
|
||||
if (!first)
|
||||
BIO_puts(out, ", ");
|
||||
BIO_puts(out, bnam->lname);
|
||||
first = 0;
|
||||
}
|
||||
}
|
||||
BIO_puts(out, "\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ASN1_BIT_STRING_set_asc(ASN1_BIT_STRING *bs, const char *name, int value,
|
||||
BIT_STRING_BITNAME *tbl)
|
||||
{
|
||||
int bitnum;
|
||||
bitnum = ASN1_BIT_STRING_num_asc(name, tbl);
|
||||
if (bitnum < 0)
|
||||
return 0;
|
||||
if (bs) {
|
||||
if (!ASN1_BIT_STRING_set_bit(bs, bitnum, value))
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ASN1_BIT_STRING_num_asc(const char *name, BIT_STRING_BITNAME *tbl)
|
||||
{
|
||||
BIT_STRING_BITNAME *bnam;
|
||||
for (bnam = tbl; bnam->lname; bnam++) {
|
||||
if ((strcmp(bnam->sname, name) == 0)
|
||||
|| (strcmp(bnam->lname, name) == 0))
|
||||
return bnam->bitnum;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
93
crypto/asn1/t_pkey.c
Normal file
93
crypto/asn1/t_pkey.c
Normal file
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
* Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "internal/cryptlib.h"
|
||||
#include <openssl/objects.h>
|
||||
#include <openssl/buffer.h>
|
||||
#include "internal/bn_int.h"
|
||||
|
||||
/* Number of octets per line */
|
||||
#define ASN1_BUF_PRINT_WIDTH 15
|
||||
/* Maximum indent */
|
||||
#define ASN1_PRINT_MAX_INDENT 128
|
||||
|
||||
int ASN1_buf_print(BIO *bp, const unsigned char *buf, size_t buflen, int indent)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < buflen; i++) {
|
||||
if ((i % ASN1_BUF_PRINT_WIDTH) == 0) {
|
||||
if (i > 0 && BIO_puts(bp, "\n") <= 0)
|
||||
return 0;
|
||||
if (!BIO_indent(bp, indent, ASN1_PRINT_MAX_INDENT))
|
||||
return 0;
|
||||
}
|
||||
/*
|
||||
* Use colon separators for each octet for compatibility as
|
||||
* this function is used to print out key components.
|
||||
*/
|
||||
if (BIO_printf(bp, "%02x%s", buf[i],
|
||||
(i == buflen - 1) ? "" : ":") <= 0)
|
||||
return 0;
|
||||
}
|
||||
if (BIO_write(bp, "\n", 1) <= 0)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ASN1_bn_print(BIO *bp, const char *number, const BIGNUM *num,
|
||||
unsigned char *ign, int indent)
|
||||
{
|
||||
int n, rv = 0;
|
||||
const char *neg;
|
||||
unsigned char *buf = NULL, *tmp = NULL;
|
||||
int buflen;
|
||||
|
||||
if (num == NULL)
|
||||
return 1;
|
||||
neg = BN_is_negative(num) ? "-" : "";
|
||||
if (!BIO_indent(bp, indent, ASN1_PRINT_MAX_INDENT))
|
||||
return 0;
|
||||
if (BN_is_zero(num)) {
|
||||
if (BIO_printf(bp, "%s 0\n", number) <= 0)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (BN_num_bytes(num) <= BN_BYTES) {
|
||||
if (BIO_printf(bp, "%s %s%lu (%s0x%lx)\n", number, neg,
|
||||
(unsigned long)bn_get_words(num)[0], neg,
|
||||
(unsigned long)bn_get_words(num)[0]) <= 0)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
buflen = BN_num_bytes(num) + 1;
|
||||
buf = tmp = OPENSSL_malloc(buflen);
|
||||
if (buf == NULL)
|
||||
goto err;
|
||||
buf[0] = 0;
|
||||
if (BIO_printf(bp, "%s%s\n", number,
|
||||
(neg[0] == '-') ? " (Negative)" : "") <= 0)
|
||||
goto err;
|
||||
n = BN_bn2bin(num, buf + 1);
|
||||
|
||||
if (buf[1] & 0x80)
|
||||
n++;
|
||||
else
|
||||
tmp++;
|
||||
|
||||
if (ASN1_buf_print(bp, tmp, n, indent + 4) == 0)
|
||||
goto err;
|
||||
rv = 1;
|
||||
err:
|
||||
OPENSSL_clear_free(buf, buflen);
|
||||
return rv;
|
||||
}
|
||||
56
crypto/asn1/t_spki.c
Normal file
56
crypto/asn1/t_spki.c
Normal file
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "internal/cryptlib.h"
|
||||
#include <openssl/x509.h>
|
||||
#include <openssl/asn1.h>
|
||||
#include <openssl/rsa.h>
|
||||
#include <openssl/dsa.h>
|
||||
#include <openssl/bn.h>
|
||||
|
||||
/* Print out an SPKI */
|
||||
|
||||
int NETSCAPE_SPKI_print(BIO *out, NETSCAPE_SPKI *spki)
|
||||
{
|
||||
EVP_PKEY *pkey;
|
||||
ASN1_IA5STRING *chal;
|
||||
ASN1_OBJECT *spkioid;
|
||||
int i, n;
|
||||
char *s;
|
||||
BIO_printf(out, "Netscape SPKI:\n");
|
||||
X509_PUBKEY_get0_param(&spkioid, NULL, NULL, NULL, spki->spkac->pubkey);
|
||||
i = OBJ_obj2nid(spkioid);
|
||||
BIO_printf(out, " Public Key Algorithm: %s\n",
|
||||
(i == NID_undef) ? "UNKNOWN" : OBJ_nid2ln(i));
|
||||
pkey = X509_PUBKEY_get(spki->spkac->pubkey);
|
||||
if (!pkey)
|
||||
BIO_printf(out, " Unable to load public key\n");
|
||||
else {
|
||||
EVP_PKEY_print_public(out, pkey, 4, NULL);
|
||||
EVP_PKEY_free(pkey);
|
||||
}
|
||||
chal = spki->spkac->challenge;
|
||||
if (chal->length)
|
||||
BIO_printf(out, " Challenge String: %s\n", chal->data);
|
||||
i = OBJ_obj2nid(spki->sig_algor.algorithm);
|
||||
BIO_printf(out, " Signature Algorithm: %s",
|
||||
(i == NID_undef) ? "UNKNOWN" : OBJ_nid2ln(i));
|
||||
|
||||
n = spki->signature->length;
|
||||
s = (char *)spki->signature->data;
|
||||
for (i = 0; i < n; i++) {
|
||||
if ((i % 18) == 0)
|
||||
BIO_write(out, "\n ", 7);
|
||||
BIO_printf(out, "%02x%s", (unsigned char)s[i],
|
||||
((i + 1) == n) ? "" : ":");
|
||||
}
|
||||
BIO_write(out, "\n", 1);
|
||||
return 1;
|
||||
}
|
||||
1160
crypto/asn1/tasn_dec.c
Normal file
1160
crypto/asn1/tasn_dec.c
Normal file
File diff suppressed because it is too large
Load Diff
609
crypto/asn1/tasn_enc.c
Normal file
609
crypto/asn1/tasn_enc.c
Normal file
@@ -0,0 +1,609 @@
|
||||
/*
|
||||
* Copyright 2000-2018 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
#include "internal/cryptlib.h"
|
||||
#include <openssl/asn1.h>
|
||||
#include <openssl/asn1t.h>
|
||||
#include <openssl/objects.h>
|
||||
#include "internal/asn1_int.h"
|
||||
#include "asn1_locl.h"
|
||||
|
||||
static int asn1_i2d_ex_primitive(ASN1_VALUE **pval, unsigned char **out,
|
||||
const ASN1_ITEM *it, int tag, int aclass);
|
||||
static int asn1_set_seq_out(STACK_OF(ASN1_VALUE) *sk, unsigned char **out,
|
||||
int skcontlen, const ASN1_ITEM *item,
|
||||
int do_sort, int iclass);
|
||||
static int asn1_template_ex_i2d(ASN1_VALUE **pval, unsigned char **out,
|
||||
const ASN1_TEMPLATE *tt, int tag, int aclass);
|
||||
static int asn1_item_flags_i2d(ASN1_VALUE *val, unsigned char **out,
|
||||
const ASN1_ITEM *it, int flags);
|
||||
static int asn1_ex_i2c(ASN1_VALUE **pval, unsigned char *cout, int *putype,
|
||||
const ASN1_ITEM *it);
|
||||
|
||||
/*
|
||||
* Top level i2d equivalents: the 'ndef' variant instructs the encoder to use
|
||||
* indefinite length constructed encoding, where appropriate
|
||||
*/
|
||||
|
||||
int ASN1_item_ndef_i2d(ASN1_VALUE *val, unsigned char **out,
|
||||
const ASN1_ITEM *it)
|
||||
{
|
||||
return asn1_item_flags_i2d(val, out, it, ASN1_TFLG_NDEF);
|
||||
}
|
||||
|
||||
int ASN1_item_i2d(ASN1_VALUE *val, unsigned char **out, const ASN1_ITEM *it)
|
||||
{
|
||||
return asn1_item_flags_i2d(val, out, it, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Encode an ASN1 item, this is use by the standard 'i2d' function. 'out'
|
||||
* points to a buffer to output the data to. The new i2d has one additional
|
||||
* feature. If the output buffer is NULL (i.e. *out == NULL) then a buffer is
|
||||
* allocated and populated with the encoding.
|
||||
*/
|
||||
|
||||
static int asn1_item_flags_i2d(ASN1_VALUE *val, unsigned char **out,
|
||||
const ASN1_ITEM *it, int flags)
|
||||
{
|
||||
if (out && !*out) {
|
||||
unsigned char *p, *buf;
|
||||
int len;
|
||||
|
||||
len = ASN1_item_ex_i2d(&val, NULL, it, -1, flags);
|
||||
if (len <= 0)
|
||||
return len;
|
||||
if ((buf = OPENSSL_malloc(len)) == NULL) {
|
||||
ASN1err(ASN1_F_ASN1_ITEM_FLAGS_I2D, ERR_R_MALLOC_FAILURE);
|
||||
return -1;
|
||||
}
|
||||
p = buf;
|
||||
ASN1_item_ex_i2d(&val, &p, it, -1, flags);
|
||||
*out = buf;
|
||||
return len;
|
||||
}
|
||||
|
||||
return ASN1_item_ex_i2d(&val, out, it, -1, flags);
|
||||
}
|
||||
|
||||
/*
|
||||
* Encode an item, taking care of IMPLICIT tagging (if any). This function
|
||||
* performs the normal item handling: it can be used in external types.
|
||||
*/
|
||||
|
||||
int ASN1_item_ex_i2d(ASN1_VALUE **pval, unsigned char **out,
|
||||
const ASN1_ITEM *it, int tag, int aclass)
|
||||
{
|
||||
const ASN1_TEMPLATE *tt = NULL;
|
||||
int i, seqcontlen, seqlen, ndef = 1;
|
||||
const ASN1_EXTERN_FUNCS *ef;
|
||||
const ASN1_AUX *aux = it->funcs;
|
||||
ASN1_aux_cb *asn1_cb = 0;
|
||||
|
||||
if ((it->itype != ASN1_ITYPE_PRIMITIVE) && !*pval)
|
||||
return 0;
|
||||
|
||||
if (aux && aux->asn1_cb)
|
||||
asn1_cb = aux->asn1_cb;
|
||||
|
||||
switch (it->itype) {
|
||||
|
||||
case ASN1_ITYPE_PRIMITIVE:
|
||||
if (it->templates)
|
||||
return asn1_template_ex_i2d(pval, out, it->templates,
|
||||
tag, aclass);
|
||||
return asn1_i2d_ex_primitive(pval, out, it, tag, aclass);
|
||||
|
||||
case ASN1_ITYPE_MSTRING:
|
||||
return asn1_i2d_ex_primitive(pval, out, it, -1, aclass);
|
||||
|
||||
case ASN1_ITYPE_CHOICE:
|
||||
if (asn1_cb && !asn1_cb(ASN1_OP_I2D_PRE, pval, it, NULL))
|
||||
return 0;
|
||||
i = asn1_get_choice_selector(pval, it);
|
||||
if ((i >= 0) && (i < it->tcount)) {
|
||||
ASN1_VALUE **pchval;
|
||||
const ASN1_TEMPLATE *chtt;
|
||||
chtt = it->templates + i;
|
||||
pchval = asn1_get_field_ptr(pval, chtt);
|
||||
return asn1_template_ex_i2d(pchval, out, chtt, -1, aclass);
|
||||
}
|
||||
/* Fixme: error condition if selector out of range */
|
||||
if (asn1_cb && !asn1_cb(ASN1_OP_I2D_POST, pval, it, NULL))
|
||||
return 0;
|
||||
break;
|
||||
|
||||
case ASN1_ITYPE_EXTERN:
|
||||
/* If new style i2d it does all the work */
|
||||
ef = it->funcs;
|
||||
return ef->asn1_ex_i2d(pval, out, it, tag, aclass);
|
||||
|
||||
case ASN1_ITYPE_NDEF_SEQUENCE:
|
||||
/* Use indefinite length constructed if requested */
|
||||
if (aclass & ASN1_TFLG_NDEF)
|
||||
ndef = 2;
|
||||
/* fall through */
|
||||
|
||||
case ASN1_ITYPE_SEQUENCE:
|
||||
i = asn1_enc_restore(&seqcontlen, out, pval, it);
|
||||
/* An error occurred */
|
||||
if (i < 0)
|
||||
return 0;
|
||||
/* We have a valid cached encoding... */
|
||||
if (i > 0)
|
||||
return seqcontlen;
|
||||
/* Otherwise carry on */
|
||||
seqcontlen = 0;
|
||||
/* If no IMPLICIT tagging set to SEQUENCE, UNIVERSAL */
|
||||
if (tag == -1) {
|
||||
tag = V_ASN1_SEQUENCE;
|
||||
/* Retain any other flags in aclass */
|
||||
aclass = (aclass & ~ASN1_TFLG_TAG_CLASS)
|
||||
| V_ASN1_UNIVERSAL;
|
||||
}
|
||||
if (asn1_cb && !asn1_cb(ASN1_OP_I2D_PRE, pval, it, NULL))
|
||||
return 0;
|
||||
/* First work out sequence content length */
|
||||
for (i = 0, tt = it->templates; i < it->tcount; tt++, i++) {
|
||||
const ASN1_TEMPLATE *seqtt;
|
||||
ASN1_VALUE **pseqval;
|
||||
int tmplen;
|
||||
seqtt = asn1_do_adb(pval, tt, 1);
|
||||
if (!seqtt)
|
||||
return 0;
|
||||
pseqval = asn1_get_field_ptr(pval, seqtt);
|
||||
tmplen = asn1_template_ex_i2d(pseqval, NULL, seqtt, -1, aclass);
|
||||
if (tmplen == -1 || (tmplen > INT_MAX - seqcontlen))
|
||||
return -1;
|
||||
seqcontlen += tmplen;
|
||||
}
|
||||
|
||||
seqlen = ASN1_object_size(ndef, seqcontlen, tag);
|
||||
if (!out || seqlen == -1)
|
||||
return seqlen;
|
||||
/* Output SEQUENCE header */
|
||||
ASN1_put_object(out, ndef, seqcontlen, tag, aclass);
|
||||
for (i = 0, tt = it->templates; i < it->tcount; tt++, i++) {
|
||||
const ASN1_TEMPLATE *seqtt;
|
||||
ASN1_VALUE **pseqval;
|
||||
seqtt = asn1_do_adb(pval, tt, 1);
|
||||
if (!seqtt)
|
||||
return 0;
|
||||
pseqval = asn1_get_field_ptr(pval, seqtt);
|
||||
/* FIXME: check for errors in enhanced version */
|
||||
asn1_template_ex_i2d(pseqval, out, seqtt, -1, aclass);
|
||||
}
|
||||
if (ndef == 2)
|
||||
ASN1_put_eoc(out);
|
||||
if (asn1_cb && !asn1_cb(ASN1_OP_I2D_POST, pval, it, NULL))
|
||||
return 0;
|
||||
return seqlen;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int asn1_template_ex_i2d(ASN1_VALUE **pval, unsigned char **out,
|
||||
const ASN1_TEMPLATE *tt, int tag, int iclass)
|
||||
{
|
||||
int i, ret, flags, ttag, tclass, ndef;
|
||||
ASN1_VALUE *tval;
|
||||
flags = tt->flags;
|
||||
|
||||
/*
|
||||
* If field is embedded then val needs fixing so it is a pointer to
|
||||
* a pointer to a field.
|
||||
*/
|
||||
if (flags & ASN1_TFLG_EMBED) {
|
||||
tval = (ASN1_VALUE *)pval;
|
||||
pval = &tval;
|
||||
}
|
||||
/*
|
||||
* Work out tag and class to use: tagging may come either from the
|
||||
* template or the arguments, not both because this would create
|
||||
* ambiguity. Additionally the iclass argument may contain some
|
||||
* additional flags which should be noted and passed down to other
|
||||
* levels.
|
||||
*/
|
||||
if (flags & ASN1_TFLG_TAG_MASK) {
|
||||
/* Error if argument and template tagging */
|
||||
if (tag != -1)
|
||||
/* FIXME: error code here */
|
||||
return -1;
|
||||
/* Get tagging from template */
|
||||
ttag = tt->tag;
|
||||
tclass = flags & ASN1_TFLG_TAG_CLASS;
|
||||
} else if (tag != -1) {
|
||||
/* No template tagging, get from arguments */
|
||||
ttag = tag;
|
||||
tclass = iclass & ASN1_TFLG_TAG_CLASS;
|
||||
} else {
|
||||
ttag = -1;
|
||||
tclass = 0;
|
||||
}
|
||||
/*
|
||||
* Remove any class mask from iflag.
|
||||
*/
|
||||
iclass &= ~ASN1_TFLG_TAG_CLASS;
|
||||
|
||||
/*
|
||||
* At this point 'ttag' contains the outer tag to use, 'tclass' is the
|
||||
* class and iclass is any flags passed to this function.
|
||||
*/
|
||||
|
||||
/* if template and arguments require ndef, use it */
|
||||
if ((flags & ASN1_TFLG_NDEF) && (iclass & ASN1_TFLG_NDEF))
|
||||
ndef = 2;
|
||||
else
|
||||
ndef = 1;
|
||||
|
||||
if (flags & ASN1_TFLG_SK_MASK) {
|
||||
/* SET OF, SEQUENCE OF */
|
||||
STACK_OF(ASN1_VALUE) *sk = (STACK_OF(ASN1_VALUE) *)*pval;
|
||||
int isset, sktag, skaclass;
|
||||
int skcontlen, sklen;
|
||||
ASN1_VALUE *skitem;
|
||||
|
||||
if (!*pval)
|
||||
return 0;
|
||||
|
||||
if (flags & ASN1_TFLG_SET_OF) {
|
||||
isset = 1;
|
||||
/* 2 means we reorder */
|
||||
if (flags & ASN1_TFLG_SEQUENCE_OF)
|
||||
isset = 2;
|
||||
} else
|
||||
isset = 0;
|
||||
|
||||
/*
|
||||
* Work out inner tag value: if EXPLICIT or no tagging use underlying
|
||||
* type.
|
||||
*/
|
||||
if ((ttag != -1) && !(flags & ASN1_TFLG_EXPTAG)) {
|
||||
sktag = ttag;
|
||||
skaclass = tclass;
|
||||
} else {
|
||||
skaclass = V_ASN1_UNIVERSAL;
|
||||
if (isset)
|
||||
sktag = V_ASN1_SET;
|
||||
else
|
||||
sktag = V_ASN1_SEQUENCE;
|
||||
}
|
||||
|
||||
/* Determine total length of items */
|
||||
skcontlen = 0;
|
||||
for (i = 0; i < sk_ASN1_VALUE_num(sk); i++) {
|
||||
int tmplen;
|
||||
skitem = sk_ASN1_VALUE_value(sk, i);
|
||||
tmplen = ASN1_item_ex_i2d(&skitem, NULL, ASN1_ITEM_ptr(tt->item),
|
||||
-1, iclass);
|
||||
if (tmplen == -1 || (skcontlen > INT_MAX - tmplen))
|
||||
return -1;
|
||||
skcontlen += tmplen;
|
||||
}
|
||||
sklen = ASN1_object_size(ndef, skcontlen, sktag);
|
||||
if (sklen == -1)
|
||||
return -1;
|
||||
/* If EXPLICIT need length of surrounding tag */
|
||||
if (flags & ASN1_TFLG_EXPTAG)
|
||||
ret = ASN1_object_size(ndef, sklen, ttag);
|
||||
else
|
||||
ret = sklen;
|
||||
|
||||
if (!out || ret == -1)
|
||||
return ret;
|
||||
|
||||
/* Now encode this lot... */
|
||||
/* EXPLICIT tag */
|
||||
if (flags & ASN1_TFLG_EXPTAG)
|
||||
ASN1_put_object(out, ndef, sklen, ttag, tclass);
|
||||
/* SET or SEQUENCE and IMPLICIT tag */
|
||||
ASN1_put_object(out, ndef, skcontlen, sktag, skaclass);
|
||||
/* And the stuff itself */
|
||||
asn1_set_seq_out(sk, out, skcontlen, ASN1_ITEM_ptr(tt->item),
|
||||
isset, iclass);
|
||||
if (ndef == 2) {
|
||||
ASN1_put_eoc(out);
|
||||
if (flags & ASN1_TFLG_EXPTAG)
|
||||
ASN1_put_eoc(out);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (flags & ASN1_TFLG_EXPTAG) {
|
||||
/* EXPLICIT tagging */
|
||||
/* Find length of tagged item */
|
||||
i = ASN1_item_ex_i2d(pval, NULL, ASN1_ITEM_ptr(tt->item), -1, iclass);
|
||||
if (!i)
|
||||
return 0;
|
||||
/* Find length of EXPLICIT tag */
|
||||
ret = ASN1_object_size(ndef, i, ttag);
|
||||
if (out && ret != -1) {
|
||||
/* Output tag and item */
|
||||
ASN1_put_object(out, ndef, i, ttag, tclass);
|
||||
ASN1_item_ex_i2d(pval, out, ASN1_ITEM_ptr(tt->item), -1, iclass);
|
||||
if (ndef == 2)
|
||||
ASN1_put_eoc(out);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Either normal or IMPLICIT tagging: combine class and flags */
|
||||
return ASN1_item_ex_i2d(pval, out, ASN1_ITEM_ptr(tt->item),
|
||||
ttag, tclass | iclass);
|
||||
|
||||
}
|
||||
|
||||
/* Temporary structure used to hold DER encoding of items for SET OF */
|
||||
|
||||
typedef struct {
|
||||
unsigned char *data;
|
||||
int length;
|
||||
ASN1_VALUE *field;
|
||||
} DER_ENC;
|
||||
|
||||
static int der_cmp(const void *a, const void *b)
|
||||
{
|
||||
const DER_ENC *d1 = a, *d2 = b;
|
||||
int cmplen, i;
|
||||
cmplen = (d1->length < d2->length) ? d1->length : d2->length;
|
||||
i = memcmp(d1->data, d2->data, cmplen);
|
||||
if (i)
|
||||
return i;
|
||||
return d1->length - d2->length;
|
||||
}
|
||||
|
||||
/* Output the content octets of SET OF or SEQUENCE OF */
|
||||
|
||||
static int asn1_set_seq_out(STACK_OF(ASN1_VALUE) *sk, unsigned char **out,
|
||||
int skcontlen, const ASN1_ITEM *item,
|
||||
int do_sort, int iclass)
|
||||
{
|
||||
int i;
|
||||
ASN1_VALUE *skitem;
|
||||
unsigned char *tmpdat = NULL, *p = NULL;
|
||||
DER_ENC *derlst = NULL, *tder;
|
||||
if (do_sort) {
|
||||
/* Don't need to sort less than 2 items */
|
||||
if (sk_ASN1_VALUE_num(sk) < 2)
|
||||
do_sort = 0;
|
||||
else {
|
||||
derlst = OPENSSL_malloc(sk_ASN1_VALUE_num(sk)
|
||||
* sizeof(*derlst));
|
||||
if (derlst == NULL)
|
||||
return 0;
|
||||
tmpdat = OPENSSL_malloc(skcontlen);
|
||||
if (tmpdat == NULL) {
|
||||
OPENSSL_free(derlst);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* If not sorting just output each item */
|
||||
if (!do_sort) {
|
||||
for (i = 0; i < sk_ASN1_VALUE_num(sk); i++) {
|
||||
skitem = sk_ASN1_VALUE_value(sk, i);
|
||||
ASN1_item_ex_i2d(&skitem, out, item, -1, iclass);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
p = tmpdat;
|
||||
|
||||
/* Doing sort: build up a list of each member's DER encoding */
|
||||
for (i = 0, tder = derlst; i < sk_ASN1_VALUE_num(sk); i++, tder++) {
|
||||
skitem = sk_ASN1_VALUE_value(sk, i);
|
||||
tder->data = p;
|
||||
tder->length = ASN1_item_ex_i2d(&skitem, &p, item, -1, iclass);
|
||||
tder->field = skitem;
|
||||
}
|
||||
|
||||
/* Now sort them */
|
||||
qsort(derlst, sk_ASN1_VALUE_num(sk), sizeof(*derlst), der_cmp);
|
||||
/* Output sorted DER encoding */
|
||||
p = *out;
|
||||
for (i = 0, tder = derlst; i < sk_ASN1_VALUE_num(sk); i++, tder++) {
|
||||
memcpy(p, tder->data, tder->length);
|
||||
p += tder->length;
|
||||
}
|
||||
*out = p;
|
||||
/* If do_sort is 2 then reorder the STACK */
|
||||
if (do_sort == 2) {
|
||||
for (i = 0, tder = derlst; i < sk_ASN1_VALUE_num(sk); i++, tder++)
|
||||
(void)sk_ASN1_VALUE_set(sk, i, tder->field);
|
||||
}
|
||||
OPENSSL_free(derlst);
|
||||
OPENSSL_free(tmpdat);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int asn1_i2d_ex_primitive(ASN1_VALUE **pval, unsigned char **out,
|
||||
const ASN1_ITEM *it, int tag, int aclass)
|
||||
{
|
||||
int len;
|
||||
int utype;
|
||||
int usetag;
|
||||
int ndef = 0;
|
||||
|
||||
utype = it->utype;
|
||||
|
||||
/*
|
||||
* Get length of content octets and maybe find out the underlying type.
|
||||
*/
|
||||
|
||||
len = asn1_ex_i2c(pval, NULL, &utype, it);
|
||||
|
||||
/*
|
||||
* If SEQUENCE, SET or OTHER then header is included in pseudo content
|
||||
* octets so don't include tag+length. We need to check here because the
|
||||
* call to asn1_ex_i2c() could change utype.
|
||||
*/
|
||||
if ((utype == V_ASN1_SEQUENCE) || (utype == V_ASN1_SET) ||
|
||||
(utype == V_ASN1_OTHER))
|
||||
usetag = 0;
|
||||
else
|
||||
usetag = 1;
|
||||
|
||||
/* -1 means omit type */
|
||||
|
||||
if (len == -1)
|
||||
return 0;
|
||||
|
||||
/* -2 return is special meaning use ndef */
|
||||
if (len == -2) {
|
||||
ndef = 2;
|
||||
len = 0;
|
||||
}
|
||||
|
||||
/* If not implicitly tagged get tag from underlying type */
|
||||
if (tag == -1)
|
||||
tag = utype;
|
||||
|
||||
/* Output tag+length followed by content octets */
|
||||
if (out) {
|
||||
if (usetag)
|
||||
ASN1_put_object(out, ndef, len, tag, aclass);
|
||||
asn1_ex_i2c(pval, *out, &utype, it);
|
||||
if (ndef)
|
||||
ASN1_put_eoc(out);
|
||||
else
|
||||
*out += len;
|
||||
}
|
||||
|
||||
if (usetag)
|
||||
return ASN1_object_size(ndef, len, tag);
|
||||
return len;
|
||||
}
|
||||
|
||||
/* Produce content octets from a structure */
|
||||
|
||||
static int asn1_ex_i2c(ASN1_VALUE **pval, unsigned char *cout, int *putype,
|
||||
const ASN1_ITEM *it)
|
||||
{
|
||||
ASN1_BOOLEAN *tbool = NULL;
|
||||
ASN1_STRING *strtmp;
|
||||
ASN1_OBJECT *otmp;
|
||||
int utype;
|
||||
const unsigned char *cont;
|
||||
unsigned char c;
|
||||
int len;
|
||||
const ASN1_PRIMITIVE_FUNCS *pf;
|
||||
pf = it->funcs;
|
||||
if (pf && pf->prim_i2c)
|
||||
return pf->prim_i2c(pval, cout, putype, it);
|
||||
|
||||
/* Should type be omitted? */
|
||||
if ((it->itype != ASN1_ITYPE_PRIMITIVE)
|
||||
|| (it->utype != V_ASN1_BOOLEAN)) {
|
||||
if (!*pval)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (it->itype == ASN1_ITYPE_MSTRING) {
|
||||
/* If MSTRING type set the underlying type */
|
||||
strtmp = (ASN1_STRING *)*pval;
|
||||
utype = strtmp->type;
|
||||
*putype = utype;
|
||||
} else if (it->utype == V_ASN1_ANY) {
|
||||
/* If ANY set type and pointer to value */
|
||||
ASN1_TYPE *typ;
|
||||
typ = (ASN1_TYPE *)*pval;
|
||||
utype = typ->type;
|
||||
*putype = utype;
|
||||
pval = &typ->value.asn1_value;
|
||||
} else
|
||||
utype = *putype;
|
||||
|
||||
switch (utype) {
|
||||
case V_ASN1_OBJECT:
|
||||
otmp = (ASN1_OBJECT *)*pval;
|
||||
cont = otmp->data;
|
||||
len = otmp->length;
|
||||
if (cont == NULL || len == 0)
|
||||
return -1;
|
||||
break;
|
||||
|
||||
case V_ASN1_NULL:
|
||||
cont = NULL;
|
||||
len = 0;
|
||||
break;
|
||||
|
||||
case V_ASN1_BOOLEAN:
|
||||
tbool = (ASN1_BOOLEAN *)pval;
|
||||
if (*tbool == -1)
|
||||
return -1;
|
||||
if (it->utype != V_ASN1_ANY) {
|
||||
/*
|
||||
* Default handling if value == size field then omit
|
||||
*/
|
||||
if (*tbool && (it->size > 0))
|
||||
return -1;
|
||||
if (!*tbool && !it->size)
|
||||
return -1;
|
||||
}
|
||||
c = (unsigned char)*tbool;
|
||||
cont = &c;
|
||||
len = 1;
|
||||
break;
|
||||
|
||||
case V_ASN1_BIT_STRING:
|
||||
return i2c_ASN1_BIT_STRING((ASN1_BIT_STRING *)*pval,
|
||||
cout ? &cout : NULL);
|
||||
|
||||
case V_ASN1_INTEGER:
|
||||
case V_ASN1_ENUMERATED:
|
||||
/*
|
||||
* These are all have the same content format as ASN1_INTEGER
|
||||
*/
|
||||
return i2c_ASN1_INTEGER((ASN1_INTEGER *)*pval, cout ? &cout : NULL);
|
||||
|
||||
case V_ASN1_OCTET_STRING:
|
||||
case V_ASN1_NUMERICSTRING:
|
||||
case V_ASN1_PRINTABLESTRING:
|
||||
case V_ASN1_T61STRING:
|
||||
case V_ASN1_VIDEOTEXSTRING:
|
||||
case V_ASN1_IA5STRING:
|
||||
case V_ASN1_UTCTIME:
|
||||
case V_ASN1_GENERALIZEDTIME:
|
||||
case V_ASN1_GRAPHICSTRING:
|
||||
case V_ASN1_VISIBLESTRING:
|
||||
case V_ASN1_GENERALSTRING:
|
||||
case V_ASN1_UNIVERSALSTRING:
|
||||
case V_ASN1_BMPSTRING:
|
||||
case V_ASN1_UTF8STRING:
|
||||
case V_ASN1_SEQUENCE:
|
||||
case V_ASN1_SET:
|
||||
default:
|
||||
/* All based on ASN1_STRING and handled the same */
|
||||
strtmp = (ASN1_STRING *)*pval;
|
||||
/* Special handling for NDEF */
|
||||
if ((it->size == ASN1_TFLG_NDEF)
|
||||
&& (strtmp->flags & ASN1_STRING_FLAG_NDEF)) {
|
||||
if (cout) {
|
||||
strtmp->data = cout;
|
||||
strtmp->length = 0;
|
||||
}
|
||||
/* Special return code */
|
||||
return -2;
|
||||
}
|
||||
cont = strtmp->data;
|
||||
len = strtmp->length;
|
||||
|
||||
break;
|
||||
|
||||
}
|
||||
if (cout && len)
|
||||
memcpy(cout, cont, len);
|
||||
return len;
|
||||
}
|
||||
208
crypto/asn1/tasn_fre.c
Normal file
208
crypto/asn1/tasn_fre.c
Normal file
@@ -0,0 +1,208 @@
|
||||
/*
|
||||
* Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#include <stddef.h>
|
||||
#include <openssl/asn1.h>
|
||||
#include <openssl/asn1t.h>
|
||||
#include <openssl/objects.h>
|
||||
#include "asn1_locl.h"
|
||||
|
||||
/* Free up an ASN1 structure */
|
||||
|
||||
void ASN1_item_free(ASN1_VALUE *val, const ASN1_ITEM *it)
|
||||
{
|
||||
asn1_item_embed_free(&val, it, 0);
|
||||
}
|
||||
|
||||
void ASN1_item_ex_free(ASN1_VALUE **pval, const ASN1_ITEM *it)
|
||||
{
|
||||
asn1_item_embed_free(pval, it, 0);
|
||||
}
|
||||
|
||||
void asn1_item_embed_free(ASN1_VALUE **pval, const ASN1_ITEM *it, int embed)
|
||||
{
|
||||
const ASN1_TEMPLATE *tt = NULL, *seqtt;
|
||||
const ASN1_EXTERN_FUNCS *ef;
|
||||
const ASN1_AUX *aux = it->funcs;
|
||||
ASN1_aux_cb *asn1_cb;
|
||||
int i;
|
||||
|
||||
if (!pval)
|
||||
return;
|
||||
if ((it->itype != ASN1_ITYPE_PRIMITIVE) && !*pval)
|
||||
return;
|
||||
if (aux && aux->asn1_cb)
|
||||
asn1_cb = aux->asn1_cb;
|
||||
else
|
||||
asn1_cb = 0;
|
||||
|
||||
switch (it->itype) {
|
||||
|
||||
case ASN1_ITYPE_PRIMITIVE:
|
||||
if (it->templates)
|
||||
asn1_template_free(pval, it->templates);
|
||||
else
|
||||
asn1_primitive_free(pval, it, embed);
|
||||
break;
|
||||
|
||||
case ASN1_ITYPE_MSTRING:
|
||||
asn1_primitive_free(pval, it, embed);
|
||||
break;
|
||||
|
||||
case ASN1_ITYPE_CHOICE:
|
||||
if (asn1_cb) {
|
||||
i = asn1_cb(ASN1_OP_FREE_PRE, pval, it, NULL);
|
||||
if (i == 2)
|
||||
return;
|
||||
}
|
||||
i = asn1_get_choice_selector(pval, it);
|
||||
if ((i >= 0) && (i < it->tcount)) {
|
||||
ASN1_VALUE **pchval;
|
||||
|
||||
tt = it->templates + i;
|
||||
pchval = asn1_get_field_ptr(pval, tt);
|
||||
asn1_template_free(pchval, tt);
|
||||
}
|
||||
if (asn1_cb)
|
||||
asn1_cb(ASN1_OP_FREE_POST, pval, it, NULL);
|
||||
if (embed == 0) {
|
||||
OPENSSL_free(*pval);
|
||||
*pval = NULL;
|
||||
}
|
||||
break;
|
||||
|
||||
case ASN1_ITYPE_EXTERN:
|
||||
ef = it->funcs;
|
||||
if (ef && ef->asn1_ex_free)
|
||||
ef->asn1_ex_free(pval, it);
|
||||
break;
|
||||
|
||||
case ASN1_ITYPE_NDEF_SEQUENCE:
|
||||
case ASN1_ITYPE_SEQUENCE:
|
||||
if (asn1_do_lock(pval, -1, it) != 0) /* if error or ref-counter > 0 */
|
||||
return;
|
||||
if (asn1_cb) {
|
||||
i = asn1_cb(ASN1_OP_FREE_PRE, pval, it, NULL);
|
||||
if (i == 2)
|
||||
return;
|
||||
}
|
||||
asn1_enc_free(pval, it);
|
||||
/*
|
||||
* If we free up as normal we will invalidate any ANY DEFINED BY
|
||||
* field and we won't be able to determine the type of the field it
|
||||
* defines. So free up in reverse order.
|
||||
*/
|
||||
tt = it->templates + it->tcount;
|
||||
for (i = 0; i < it->tcount; i++) {
|
||||
ASN1_VALUE **pseqval;
|
||||
|
||||
tt--;
|
||||
seqtt = asn1_do_adb(pval, tt, 0);
|
||||
if (!seqtt)
|
||||
continue;
|
||||
pseqval = asn1_get_field_ptr(pval, seqtt);
|
||||
asn1_template_free(pseqval, seqtt);
|
||||
}
|
||||
if (asn1_cb)
|
||||
asn1_cb(ASN1_OP_FREE_POST, pval, it, NULL);
|
||||
if (embed == 0) {
|
||||
OPENSSL_free(*pval);
|
||||
*pval = NULL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void asn1_template_free(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt)
|
||||
{
|
||||
int embed = tt->flags & ASN1_TFLG_EMBED;
|
||||
ASN1_VALUE *tval;
|
||||
if (embed) {
|
||||
tval = (ASN1_VALUE *)pval;
|
||||
pval = &tval;
|
||||
}
|
||||
if (tt->flags & ASN1_TFLG_SK_MASK) {
|
||||
STACK_OF(ASN1_VALUE) *sk = (STACK_OF(ASN1_VALUE) *)*pval;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < sk_ASN1_VALUE_num(sk); i++) {
|
||||
ASN1_VALUE *vtmp = sk_ASN1_VALUE_value(sk, i);
|
||||
|
||||
asn1_item_embed_free(&vtmp, ASN1_ITEM_ptr(tt->item), embed);
|
||||
}
|
||||
sk_ASN1_VALUE_free(sk);
|
||||
*pval = NULL;
|
||||
} else {
|
||||
asn1_item_embed_free(pval, ASN1_ITEM_ptr(tt->item), embed);
|
||||
}
|
||||
}
|
||||
|
||||
void asn1_primitive_free(ASN1_VALUE **pval, const ASN1_ITEM *it, int embed)
|
||||
{
|
||||
int utype;
|
||||
|
||||
/* Special case: if 'it' is a primitive with a free_func, use that. */
|
||||
if (it) {
|
||||
const ASN1_PRIMITIVE_FUNCS *pf = it->funcs;
|
||||
|
||||
if (embed) {
|
||||
if (pf && pf->prim_clear) {
|
||||
pf->prim_clear(pval, it);
|
||||
return;
|
||||
}
|
||||
} else if (pf && pf->prim_free) {
|
||||
pf->prim_free(pval, it);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* Special case: if 'it' is NULL, free contents of ASN1_TYPE */
|
||||
if (!it) {
|
||||
ASN1_TYPE *typ = (ASN1_TYPE *)*pval;
|
||||
|
||||
utype = typ->type;
|
||||
pval = &typ->value.asn1_value;
|
||||
if (!*pval)
|
||||
return;
|
||||
} else if (it->itype == ASN1_ITYPE_MSTRING) {
|
||||
utype = -1;
|
||||
if (!*pval)
|
||||
return;
|
||||
} else {
|
||||
utype = it->utype;
|
||||
if ((utype != V_ASN1_BOOLEAN) && !*pval)
|
||||
return;
|
||||
}
|
||||
|
||||
switch (utype) {
|
||||
case V_ASN1_OBJECT:
|
||||
ASN1_OBJECT_free((ASN1_OBJECT *)*pval);
|
||||
break;
|
||||
|
||||
case V_ASN1_BOOLEAN:
|
||||
if (it)
|
||||
*(ASN1_BOOLEAN *)pval = it->size;
|
||||
else
|
||||
*(ASN1_BOOLEAN *)pval = -1;
|
||||
return;
|
||||
|
||||
case V_ASN1_NULL:
|
||||
break;
|
||||
|
||||
case V_ASN1_ANY:
|
||||
asn1_primitive_free(pval, NULL, 0);
|
||||
OPENSSL_free(*pval);
|
||||
break;
|
||||
|
||||
default:
|
||||
asn1_string_embed_free((ASN1_STRING *)*pval, embed);
|
||||
break;
|
||||
}
|
||||
*pval = NULL;
|
||||
}
|
||||
349
crypto/asn1/tasn_new.c
Normal file
349
crypto/asn1/tasn_new.c
Normal file
@@ -0,0 +1,349 @@
|
||||
/*
|
||||
* Copyright 2000-2018 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#include <stddef.h>
|
||||
#include <openssl/asn1.h>
|
||||
#include <openssl/objects.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/asn1t.h>
|
||||
#include <string.h>
|
||||
#include "asn1_locl.h"
|
||||
|
||||
static int asn1_item_embed_new(ASN1_VALUE **pval, const ASN1_ITEM *it,
|
||||
int embed);
|
||||
static int asn1_primitive_new(ASN1_VALUE **pval, const ASN1_ITEM *it,
|
||||
int embed);
|
||||
static void asn1_item_clear(ASN1_VALUE **pval, const ASN1_ITEM *it);
|
||||
static int asn1_template_new(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt);
|
||||
static void asn1_template_clear(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt);
|
||||
static void asn1_primitive_clear(ASN1_VALUE **pval, const ASN1_ITEM *it);
|
||||
|
||||
ASN1_VALUE *ASN1_item_new(const ASN1_ITEM *it)
|
||||
{
|
||||
ASN1_VALUE *ret = NULL;
|
||||
if (ASN1_item_ex_new(&ret, it) > 0)
|
||||
return ret;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Allocate an ASN1 structure */
|
||||
|
||||
int ASN1_item_ex_new(ASN1_VALUE **pval, const ASN1_ITEM *it)
|
||||
{
|
||||
return asn1_item_embed_new(pval, it, 0);
|
||||
}
|
||||
|
||||
int asn1_item_embed_new(ASN1_VALUE **pval, const ASN1_ITEM *it, int embed)
|
||||
{
|
||||
const ASN1_TEMPLATE *tt = NULL;
|
||||
const ASN1_EXTERN_FUNCS *ef;
|
||||
const ASN1_AUX *aux = it->funcs;
|
||||
ASN1_aux_cb *asn1_cb;
|
||||
ASN1_VALUE **pseqval;
|
||||
int i;
|
||||
if (aux && aux->asn1_cb)
|
||||
asn1_cb = aux->asn1_cb;
|
||||
else
|
||||
asn1_cb = 0;
|
||||
|
||||
#ifndef OPENSSL_NO_CRYPTO_MDEBUG
|
||||
OPENSSL_mem_debug_push(it->sname ? it->sname : "asn1_item_embed_new");
|
||||
#endif
|
||||
|
||||
switch (it->itype) {
|
||||
|
||||
case ASN1_ITYPE_EXTERN:
|
||||
ef = it->funcs;
|
||||
if (ef && ef->asn1_ex_new) {
|
||||
if (!ef->asn1_ex_new(pval, it))
|
||||
goto memerr;
|
||||
}
|
||||
break;
|
||||
|
||||
case ASN1_ITYPE_PRIMITIVE:
|
||||
if (it->templates) {
|
||||
if (!asn1_template_new(pval, it->templates))
|
||||
goto memerr;
|
||||
} else if (!asn1_primitive_new(pval, it, embed))
|
||||
goto memerr;
|
||||
break;
|
||||
|
||||
case ASN1_ITYPE_MSTRING:
|
||||
if (!asn1_primitive_new(pval, it, embed))
|
||||
goto memerr;
|
||||
break;
|
||||
|
||||
case ASN1_ITYPE_CHOICE:
|
||||
if (asn1_cb) {
|
||||
i = asn1_cb(ASN1_OP_NEW_PRE, pval, it, NULL);
|
||||
if (!i)
|
||||
goto auxerr;
|
||||
if (i == 2) {
|
||||
#ifndef OPENSSL_NO_CRYPTO_MDEBUG
|
||||
OPENSSL_mem_debug_pop();
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
if (embed) {
|
||||
memset(*pval, 0, it->size);
|
||||
} else {
|
||||
*pval = OPENSSL_zalloc(it->size);
|
||||
if (*pval == NULL)
|
||||
goto memerr;
|
||||
}
|
||||
asn1_set_choice_selector(pval, -1, it);
|
||||
if (asn1_cb && !asn1_cb(ASN1_OP_NEW_POST, pval, it, NULL))
|
||||
goto auxerr2;
|
||||
break;
|
||||
|
||||
case ASN1_ITYPE_NDEF_SEQUENCE:
|
||||
case ASN1_ITYPE_SEQUENCE:
|
||||
if (asn1_cb) {
|
||||
i = asn1_cb(ASN1_OP_NEW_PRE, pval, it, NULL);
|
||||
if (!i)
|
||||
goto auxerr;
|
||||
if (i == 2) {
|
||||
#ifndef OPENSSL_NO_CRYPTO_MDEBUG
|
||||
OPENSSL_mem_debug_pop();
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
if (embed) {
|
||||
memset(*pval, 0, it->size);
|
||||
} else {
|
||||
*pval = OPENSSL_zalloc(it->size);
|
||||
if (*pval == NULL)
|
||||
goto memerr;
|
||||
}
|
||||
/* 0 : init. lock */
|
||||
if (asn1_do_lock(pval, 0, it) < 0) {
|
||||
if (!embed) {
|
||||
OPENSSL_free(*pval);
|
||||
*pval = NULL;
|
||||
}
|
||||
goto memerr;
|
||||
}
|
||||
asn1_enc_init(pval, it);
|
||||
for (i = 0, tt = it->templates; i < it->tcount; tt++, i++) {
|
||||
pseqval = asn1_get_field_ptr(pval, tt);
|
||||
if (!asn1_template_new(pseqval, tt))
|
||||
goto memerr2;
|
||||
}
|
||||
if (asn1_cb && !asn1_cb(ASN1_OP_NEW_POST, pval, it, NULL))
|
||||
goto auxerr2;
|
||||
break;
|
||||
}
|
||||
#ifndef OPENSSL_NO_CRYPTO_MDEBUG
|
||||
OPENSSL_mem_debug_pop();
|
||||
#endif
|
||||
return 1;
|
||||
|
||||
memerr2:
|
||||
asn1_item_embed_free(pval, it, embed);
|
||||
memerr:
|
||||
ASN1err(ASN1_F_ASN1_ITEM_EMBED_NEW, ERR_R_MALLOC_FAILURE);
|
||||
#ifndef OPENSSL_NO_CRYPTO_MDEBUG
|
||||
OPENSSL_mem_debug_pop();
|
||||
#endif
|
||||
return 0;
|
||||
|
||||
auxerr2:
|
||||
asn1_item_embed_free(pval, it, embed);
|
||||
auxerr:
|
||||
ASN1err(ASN1_F_ASN1_ITEM_EMBED_NEW, ASN1_R_AUX_ERROR);
|
||||
#ifndef OPENSSL_NO_CRYPTO_MDEBUG
|
||||
OPENSSL_mem_debug_pop();
|
||||
#endif
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
static void asn1_item_clear(ASN1_VALUE **pval, const ASN1_ITEM *it)
|
||||
{
|
||||
const ASN1_EXTERN_FUNCS *ef;
|
||||
|
||||
switch (it->itype) {
|
||||
|
||||
case ASN1_ITYPE_EXTERN:
|
||||
ef = it->funcs;
|
||||
if (ef && ef->asn1_ex_clear)
|
||||
ef->asn1_ex_clear(pval, it);
|
||||
else
|
||||
*pval = NULL;
|
||||
break;
|
||||
|
||||
case ASN1_ITYPE_PRIMITIVE:
|
||||
if (it->templates)
|
||||
asn1_template_clear(pval, it->templates);
|
||||
else
|
||||
asn1_primitive_clear(pval, it);
|
||||
break;
|
||||
|
||||
case ASN1_ITYPE_MSTRING:
|
||||
asn1_primitive_clear(pval, it);
|
||||
break;
|
||||
|
||||
case ASN1_ITYPE_CHOICE:
|
||||
case ASN1_ITYPE_SEQUENCE:
|
||||
case ASN1_ITYPE_NDEF_SEQUENCE:
|
||||
*pval = NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static int asn1_template_new(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt)
|
||||
{
|
||||
const ASN1_ITEM *it = ASN1_ITEM_ptr(tt->item);
|
||||
int embed = tt->flags & ASN1_TFLG_EMBED;
|
||||
ASN1_VALUE *tval;
|
||||
int ret;
|
||||
if (embed) {
|
||||
tval = (ASN1_VALUE *)pval;
|
||||
pval = &tval;
|
||||
}
|
||||
if (tt->flags & ASN1_TFLG_OPTIONAL) {
|
||||
asn1_template_clear(pval, tt);
|
||||
return 1;
|
||||
}
|
||||
/* If ANY DEFINED BY nothing to do */
|
||||
|
||||
if (tt->flags & ASN1_TFLG_ADB_MASK) {
|
||||
*pval = NULL;
|
||||
return 1;
|
||||
}
|
||||
#ifndef OPENSSL_NO_CRYPTO_MDEBUG
|
||||
OPENSSL_mem_debug_push(tt->field_name
|
||||
? tt->field_name : "asn1_template_new");
|
||||
#endif
|
||||
/* If SET OF or SEQUENCE OF, its a STACK */
|
||||
if (tt->flags & ASN1_TFLG_SK_MASK) {
|
||||
STACK_OF(ASN1_VALUE) *skval;
|
||||
skval = sk_ASN1_VALUE_new_null();
|
||||
if (!skval) {
|
||||
ASN1err(ASN1_F_ASN1_TEMPLATE_NEW, ERR_R_MALLOC_FAILURE);
|
||||
ret = 0;
|
||||
goto done;
|
||||
}
|
||||
*pval = (ASN1_VALUE *)skval;
|
||||
ret = 1;
|
||||
goto done;
|
||||
}
|
||||
/* Otherwise pass it back to the item routine */
|
||||
ret = asn1_item_embed_new(pval, it, embed);
|
||||
done:
|
||||
#ifndef OPENSSL_NO_CRYPTO_MDEBUG
|
||||
OPENSSL_mem_debug_pop();
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void asn1_template_clear(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt)
|
||||
{
|
||||
/* If ADB or STACK just NULL the field */
|
||||
if (tt->flags & (ASN1_TFLG_ADB_MASK | ASN1_TFLG_SK_MASK))
|
||||
*pval = NULL;
|
||||
else
|
||||
asn1_item_clear(pval, ASN1_ITEM_ptr(tt->item));
|
||||
}
|
||||
|
||||
/*
|
||||
* NB: could probably combine most of the real XXX_new() behaviour and junk
|
||||
* all the old functions.
|
||||
*/
|
||||
|
||||
static int asn1_primitive_new(ASN1_VALUE **pval, const ASN1_ITEM *it,
|
||||
int embed)
|
||||
{
|
||||
ASN1_TYPE *typ;
|
||||
ASN1_STRING *str;
|
||||
int utype;
|
||||
|
||||
if (!it)
|
||||
return 0;
|
||||
|
||||
if (it->funcs) {
|
||||
const ASN1_PRIMITIVE_FUNCS *pf = it->funcs;
|
||||
if (embed) {
|
||||
if (pf->prim_clear) {
|
||||
pf->prim_clear(pval, it);
|
||||
return 1;
|
||||
}
|
||||
} else if (pf->prim_new) {
|
||||
return pf->prim_new(pval, it);
|
||||
}
|
||||
}
|
||||
|
||||
if (it->itype == ASN1_ITYPE_MSTRING)
|
||||
utype = -1;
|
||||
else
|
||||
utype = it->utype;
|
||||
switch (utype) {
|
||||
case V_ASN1_OBJECT:
|
||||
*pval = (ASN1_VALUE *)OBJ_nid2obj(NID_undef);
|
||||
return 1;
|
||||
|
||||
case V_ASN1_BOOLEAN:
|
||||
*(ASN1_BOOLEAN *)pval = it->size;
|
||||
return 1;
|
||||
|
||||
case V_ASN1_NULL:
|
||||
*pval = (ASN1_VALUE *)1;
|
||||
return 1;
|
||||
|
||||
case V_ASN1_ANY:
|
||||
if ((typ = OPENSSL_malloc(sizeof(*typ))) == NULL) {
|
||||
ASN1err(ASN1_F_ASN1_PRIMITIVE_NEW, ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
typ->value.ptr = NULL;
|
||||
typ->type = -1;
|
||||
*pval = (ASN1_VALUE *)typ;
|
||||
break;
|
||||
|
||||
default:
|
||||
if (embed) {
|
||||
str = *(ASN1_STRING **)pval;
|
||||
memset(str, 0, sizeof(*str));
|
||||
str->type = utype;
|
||||
str->flags = ASN1_STRING_FLAG_EMBED;
|
||||
} else {
|
||||
str = ASN1_STRING_type_new(utype);
|
||||
*pval = (ASN1_VALUE *)str;
|
||||
}
|
||||
if (it->itype == ASN1_ITYPE_MSTRING && str)
|
||||
str->flags |= ASN1_STRING_FLAG_MSTRING;
|
||||
break;
|
||||
}
|
||||
if (*pval)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void asn1_primitive_clear(ASN1_VALUE **pval, const ASN1_ITEM *it)
|
||||
{
|
||||
int utype;
|
||||
if (it && it->funcs) {
|
||||
const ASN1_PRIMITIVE_FUNCS *pf = it->funcs;
|
||||
if (pf->prim_clear)
|
||||
pf->prim_clear(pval, it);
|
||||
else
|
||||
*pval = NULL;
|
||||
return;
|
||||
}
|
||||
if (!it || (it->itype == ASN1_ITYPE_MSTRING))
|
||||
utype = -1;
|
||||
else
|
||||
utype = it->utype;
|
||||
if (utype == V_ASN1_BOOLEAN)
|
||||
*(ASN1_BOOLEAN *)pval = it->size;
|
||||
else
|
||||
*pval = NULL;
|
||||
}
|
||||
539
crypto/asn1/tasn_prn.c
Normal file
539
crypto/asn1/tasn_prn.c
Normal file
@@ -0,0 +1,539 @@
|
||||
/*
|
||||
* Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#include <stddef.h>
|
||||
#include "internal/cryptlib.h"
|
||||
#include <openssl/asn1.h>
|
||||
#include <openssl/asn1t.h>
|
||||
#include <openssl/objects.h>
|
||||
#include <openssl/buffer.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/x509v3.h>
|
||||
#include "internal/asn1_int.h"
|
||||
#include "asn1_locl.h"
|
||||
|
||||
/*
|
||||
* Print routines.
|
||||
*/
|
||||
|
||||
/* ASN1_PCTX routines */
|
||||
|
||||
static ASN1_PCTX default_pctx = {
|
||||
ASN1_PCTX_FLAGS_SHOW_ABSENT, /* flags */
|
||||
0, /* nm_flags */
|
||||
0, /* cert_flags */
|
||||
0, /* oid_flags */
|
||||
0 /* str_flags */
|
||||
};
|
||||
|
||||
ASN1_PCTX *ASN1_PCTX_new(void)
|
||||
{
|
||||
ASN1_PCTX *ret;
|
||||
|
||||
ret = OPENSSL_zalloc(sizeof(*ret));
|
||||
if (ret == NULL) {
|
||||
ASN1err(ASN1_F_ASN1_PCTX_NEW, ERR_R_MALLOC_FAILURE);
|
||||
return NULL;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void ASN1_PCTX_free(ASN1_PCTX *p)
|
||||
{
|
||||
OPENSSL_free(p);
|
||||
}
|
||||
|
||||
unsigned long ASN1_PCTX_get_flags(const ASN1_PCTX *p)
|
||||
{
|
||||
return p->flags;
|
||||
}
|
||||
|
||||
void ASN1_PCTX_set_flags(ASN1_PCTX *p, unsigned long flags)
|
||||
{
|
||||
p->flags = flags;
|
||||
}
|
||||
|
||||
unsigned long ASN1_PCTX_get_nm_flags(const ASN1_PCTX *p)
|
||||
{
|
||||
return p->nm_flags;
|
||||
}
|
||||
|
||||
void ASN1_PCTX_set_nm_flags(ASN1_PCTX *p, unsigned long flags)
|
||||
{
|
||||
p->nm_flags = flags;
|
||||
}
|
||||
|
||||
unsigned long ASN1_PCTX_get_cert_flags(const ASN1_PCTX *p)
|
||||
{
|
||||
return p->cert_flags;
|
||||
}
|
||||
|
||||
void ASN1_PCTX_set_cert_flags(ASN1_PCTX *p, unsigned long flags)
|
||||
{
|
||||
p->cert_flags = flags;
|
||||
}
|
||||
|
||||
unsigned long ASN1_PCTX_get_oid_flags(const ASN1_PCTX *p)
|
||||
{
|
||||
return p->oid_flags;
|
||||
}
|
||||
|
||||
void ASN1_PCTX_set_oid_flags(ASN1_PCTX *p, unsigned long flags)
|
||||
{
|
||||
p->oid_flags = flags;
|
||||
}
|
||||
|
||||
unsigned long ASN1_PCTX_get_str_flags(const ASN1_PCTX *p)
|
||||
{
|
||||
return p->str_flags;
|
||||
}
|
||||
|
||||
void ASN1_PCTX_set_str_flags(ASN1_PCTX *p, unsigned long flags)
|
||||
{
|
||||
p->str_flags = flags;
|
||||
}
|
||||
|
||||
/* Main print routines */
|
||||
|
||||
static int asn1_item_print_ctx(BIO *out, ASN1_VALUE **fld, int indent,
|
||||
const ASN1_ITEM *it,
|
||||
const char *fname, const char *sname,
|
||||
int nohdr, const ASN1_PCTX *pctx);
|
||||
|
||||
static int asn1_template_print_ctx(BIO *out, ASN1_VALUE **fld, int indent,
|
||||
const ASN1_TEMPLATE *tt, const ASN1_PCTX *pctx);
|
||||
|
||||
static int asn1_primitive_print(BIO *out, ASN1_VALUE **fld,
|
||||
const ASN1_ITEM *it, int indent,
|
||||
const char *fname, const char *sname,
|
||||
const ASN1_PCTX *pctx);
|
||||
|
||||
static int asn1_print_fsname(BIO *out, int indent,
|
||||
const char *fname, const char *sname,
|
||||
const ASN1_PCTX *pctx);
|
||||
|
||||
int ASN1_item_print(BIO *out, ASN1_VALUE *ifld, int indent,
|
||||
const ASN1_ITEM *it, const ASN1_PCTX *pctx)
|
||||
{
|
||||
const char *sname;
|
||||
if (pctx == NULL)
|
||||
pctx = &default_pctx;
|
||||
if (pctx->flags & ASN1_PCTX_FLAGS_NO_STRUCT_NAME)
|
||||
sname = NULL;
|
||||
else
|
||||
sname = it->sname;
|
||||
return asn1_item_print_ctx(out, &ifld, indent, it, NULL, sname, 0, pctx);
|
||||
}
|
||||
|
||||
static int asn1_item_print_ctx(BIO *out, ASN1_VALUE **fld, int indent,
|
||||
const ASN1_ITEM *it,
|
||||
const char *fname, const char *sname,
|
||||
int nohdr, const ASN1_PCTX *pctx)
|
||||
{
|
||||
const ASN1_TEMPLATE *tt;
|
||||
const ASN1_EXTERN_FUNCS *ef;
|
||||
ASN1_VALUE **tmpfld;
|
||||
const ASN1_AUX *aux = it->funcs;
|
||||
ASN1_aux_cb *asn1_cb;
|
||||
ASN1_PRINT_ARG parg;
|
||||
int i;
|
||||
if (aux && aux->asn1_cb) {
|
||||
parg.out = out;
|
||||
parg.indent = indent;
|
||||
parg.pctx = pctx;
|
||||
asn1_cb = aux->asn1_cb;
|
||||
} else
|
||||
asn1_cb = 0;
|
||||
|
||||
if (((it->itype != ASN1_ITYPE_PRIMITIVE)
|
||||
|| (it->utype != V_ASN1_BOOLEAN)) && *fld == NULL) {
|
||||
if (pctx->flags & ASN1_PCTX_FLAGS_SHOW_ABSENT) {
|
||||
if (!nohdr && !asn1_print_fsname(out, indent, fname, sname, pctx))
|
||||
return 0;
|
||||
if (BIO_puts(out, "<ABSENT>\n") <= 0)
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
switch (it->itype) {
|
||||
case ASN1_ITYPE_PRIMITIVE:
|
||||
if (it->templates) {
|
||||
if (!asn1_template_print_ctx(out, fld, indent,
|
||||
it->templates, pctx))
|
||||
return 0;
|
||||
break;
|
||||
}
|
||||
/* fall through */
|
||||
case ASN1_ITYPE_MSTRING:
|
||||
if (!asn1_primitive_print(out, fld, it, indent, fname, sname, pctx))
|
||||
return 0;
|
||||
break;
|
||||
|
||||
case ASN1_ITYPE_EXTERN:
|
||||
if (!nohdr && !asn1_print_fsname(out, indent, fname, sname, pctx))
|
||||
return 0;
|
||||
/* Use new style print routine if possible */
|
||||
ef = it->funcs;
|
||||
if (ef && ef->asn1_ex_print) {
|
||||
i = ef->asn1_ex_print(out, fld, indent, "", pctx);
|
||||
if (!i)
|
||||
return 0;
|
||||
if ((i == 2) && (BIO_puts(out, "\n") <= 0))
|
||||
return 0;
|
||||
return 1;
|
||||
} else if (sname &&
|
||||
BIO_printf(out, ":EXTERNAL TYPE %s\n", sname) <= 0)
|
||||
return 0;
|
||||
break;
|
||||
|
||||
case ASN1_ITYPE_CHOICE:
|
||||
/* CHOICE type, get selector */
|
||||
i = asn1_get_choice_selector(fld, it);
|
||||
/* This should never happen... */
|
||||
if ((i < 0) || (i >= it->tcount)) {
|
||||
if (BIO_printf(out, "ERROR: selector [%d] invalid\n", i) <= 0)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
tt = it->templates + i;
|
||||
tmpfld = asn1_get_field_ptr(fld, tt);
|
||||
if (!asn1_template_print_ctx(out, tmpfld, indent, tt, pctx))
|
||||
return 0;
|
||||
break;
|
||||
|
||||
case ASN1_ITYPE_SEQUENCE:
|
||||
case ASN1_ITYPE_NDEF_SEQUENCE:
|
||||
if (!nohdr && !asn1_print_fsname(out, indent, fname, sname, pctx))
|
||||
return 0;
|
||||
if (fname || sname) {
|
||||
if (pctx->flags & ASN1_PCTX_FLAGS_SHOW_SEQUENCE) {
|
||||
if (BIO_puts(out, " {\n") <= 0)
|
||||
return 0;
|
||||
} else {
|
||||
if (BIO_puts(out, "\n") <= 0)
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (asn1_cb) {
|
||||
i = asn1_cb(ASN1_OP_PRINT_PRE, fld, it, &parg);
|
||||
if (i == 0)
|
||||
return 0;
|
||||
if (i == 2)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Print each field entry */
|
||||
for (i = 0, tt = it->templates; i < it->tcount; i++, tt++) {
|
||||
const ASN1_TEMPLATE *seqtt;
|
||||
seqtt = asn1_do_adb(fld, tt, 1);
|
||||
if (!seqtt)
|
||||
return 0;
|
||||
tmpfld = asn1_get_field_ptr(fld, seqtt);
|
||||
if (!asn1_template_print_ctx(out, tmpfld,
|
||||
indent + 2, seqtt, pctx))
|
||||
return 0;
|
||||
}
|
||||
if (pctx->flags & ASN1_PCTX_FLAGS_SHOW_SEQUENCE) {
|
||||
if (BIO_printf(out, "%*s}\n", indent, "") < 0)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (asn1_cb) {
|
||||
i = asn1_cb(ASN1_OP_PRINT_POST, fld, it, &parg);
|
||||
if (i == 0)
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
BIO_printf(out, "Unprocessed type %d\n", it->itype);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int asn1_template_print_ctx(BIO *out, ASN1_VALUE **fld, int indent,
|
||||
const ASN1_TEMPLATE *tt, const ASN1_PCTX *pctx)
|
||||
{
|
||||
int i, flags;
|
||||
const char *sname, *fname;
|
||||
ASN1_VALUE *tfld;
|
||||
flags = tt->flags;
|
||||
if (pctx->flags & ASN1_PCTX_FLAGS_SHOW_FIELD_STRUCT_NAME)
|
||||
sname = ASN1_ITEM_ptr(tt->item)->sname;
|
||||
else
|
||||
sname = NULL;
|
||||
if (pctx->flags & ASN1_PCTX_FLAGS_NO_FIELD_NAME)
|
||||
fname = NULL;
|
||||
else
|
||||
fname = tt->field_name;
|
||||
|
||||
/*
|
||||
* If field is embedded then fld needs fixing so it is a pointer to
|
||||
* a pointer to a field.
|
||||
*/
|
||||
if (flags & ASN1_TFLG_EMBED) {
|
||||
tfld = (ASN1_VALUE *)fld;
|
||||
fld = &tfld;
|
||||
}
|
||||
|
||||
if (flags & ASN1_TFLG_SK_MASK) {
|
||||
char *tname;
|
||||
ASN1_VALUE *skitem;
|
||||
STACK_OF(ASN1_VALUE) *stack;
|
||||
|
||||
/* SET OF, SEQUENCE OF */
|
||||
if (fname) {
|
||||
if (pctx->flags & ASN1_PCTX_FLAGS_SHOW_SSOF) {
|
||||
if (flags & ASN1_TFLG_SET_OF)
|
||||
tname = "SET";
|
||||
else
|
||||
tname = "SEQUENCE";
|
||||
if (BIO_printf(out, "%*s%s OF %s {\n",
|
||||
indent, "", tname, tt->field_name) <= 0)
|
||||
return 0;
|
||||
} else if (BIO_printf(out, "%*s%s:\n", indent, "", fname) <= 0)
|
||||
return 0;
|
||||
}
|
||||
stack = (STACK_OF(ASN1_VALUE) *)*fld;
|
||||
for (i = 0; i < sk_ASN1_VALUE_num(stack); i++) {
|
||||
if ((i > 0) && (BIO_puts(out, "\n") <= 0))
|
||||
return 0;
|
||||
|
||||
skitem = sk_ASN1_VALUE_value(stack, i);
|
||||
if (!asn1_item_print_ctx(out, &skitem, indent + 2,
|
||||
ASN1_ITEM_ptr(tt->item), NULL, NULL, 1,
|
||||
pctx))
|
||||
return 0;
|
||||
}
|
||||
if (i == 0 && BIO_printf(out, "%*s<%s>\n", indent + 2, "",
|
||||
stack == NULL ? "ABSENT" : "EMPTY") <= 0)
|
||||
return 0;
|
||||
if (pctx->flags & ASN1_PCTX_FLAGS_SHOW_SEQUENCE) {
|
||||
if (BIO_printf(out, "%*s}\n", indent, "") <= 0)
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
return asn1_item_print_ctx(out, fld, indent, ASN1_ITEM_ptr(tt->item),
|
||||
fname, sname, 0, pctx);
|
||||
}
|
||||
|
||||
static int asn1_print_fsname(BIO *out, int indent,
|
||||
const char *fname, const char *sname,
|
||||
const ASN1_PCTX *pctx)
|
||||
{
|
||||
static const char spaces[] = " ";
|
||||
static const int nspaces = sizeof(spaces) - 1;
|
||||
|
||||
while (indent > nspaces) {
|
||||
if (BIO_write(out, spaces, nspaces) != nspaces)
|
||||
return 0;
|
||||
indent -= nspaces;
|
||||
}
|
||||
if (BIO_write(out, spaces, indent) != indent)
|
||||
return 0;
|
||||
if (pctx->flags & ASN1_PCTX_FLAGS_NO_STRUCT_NAME)
|
||||
sname = NULL;
|
||||
if (pctx->flags & ASN1_PCTX_FLAGS_NO_FIELD_NAME)
|
||||
fname = NULL;
|
||||
if (!sname && !fname)
|
||||
return 1;
|
||||
if (fname) {
|
||||
if (BIO_puts(out, fname) <= 0)
|
||||
return 0;
|
||||
}
|
||||
if (sname) {
|
||||
if (fname) {
|
||||
if (BIO_printf(out, " (%s)", sname) <= 0)
|
||||
return 0;
|
||||
} else {
|
||||
if (BIO_puts(out, sname) <= 0)
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if (BIO_write(out, ": ", 2) != 2)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int asn1_print_boolean(BIO *out, int boolval)
|
||||
{
|
||||
const char *str;
|
||||
switch (boolval) {
|
||||
case -1:
|
||||
str = "BOOL ABSENT";
|
||||
break;
|
||||
|
||||
case 0:
|
||||
str = "FALSE";
|
||||
break;
|
||||
|
||||
default:
|
||||
str = "TRUE";
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
if (BIO_puts(out, str) <= 0)
|
||||
return 0;
|
||||
return 1;
|
||||
|
||||
}
|
||||
|
||||
static int asn1_print_integer(BIO *out, const ASN1_INTEGER *str)
|
||||
{
|
||||
char *s;
|
||||
int ret = 1;
|
||||
s = i2s_ASN1_INTEGER(NULL, str);
|
||||
if (s == NULL)
|
||||
return 0;
|
||||
if (BIO_puts(out, s) <= 0)
|
||||
ret = 0;
|
||||
OPENSSL_free(s);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int asn1_print_oid(BIO *out, const ASN1_OBJECT *oid)
|
||||
{
|
||||
char objbuf[80];
|
||||
const char *ln;
|
||||
ln = OBJ_nid2ln(OBJ_obj2nid(oid));
|
||||
if (!ln)
|
||||
ln = "";
|
||||
OBJ_obj2txt(objbuf, sizeof(objbuf), oid, 1);
|
||||
if (BIO_printf(out, "%s (%s)", ln, objbuf) <= 0)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int asn1_print_obstring(BIO *out, const ASN1_STRING *str, int indent)
|
||||
{
|
||||
if (str->type == V_ASN1_BIT_STRING) {
|
||||
if (BIO_printf(out, " (%ld unused bits)\n", str->flags & 0x7) <= 0)
|
||||
return 0;
|
||||
} else if (BIO_puts(out, "\n") <= 0)
|
||||
return 0;
|
||||
if ((str->length > 0)
|
||||
&& BIO_dump_indent(out, (const char *)str->data, str->length,
|
||||
indent + 2) <= 0)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int asn1_primitive_print(BIO *out, ASN1_VALUE **fld,
|
||||
const ASN1_ITEM *it, int indent,
|
||||
const char *fname, const char *sname,
|
||||
const ASN1_PCTX *pctx)
|
||||
{
|
||||
long utype;
|
||||
ASN1_STRING *str;
|
||||
int ret = 1, needlf = 1;
|
||||
const char *pname;
|
||||
const ASN1_PRIMITIVE_FUNCS *pf;
|
||||
pf = it->funcs;
|
||||
if (!asn1_print_fsname(out, indent, fname, sname, pctx))
|
||||
return 0;
|
||||
if (pf && pf->prim_print)
|
||||
return pf->prim_print(out, fld, it, indent, pctx);
|
||||
if (it->itype == ASN1_ITYPE_MSTRING) {
|
||||
str = (ASN1_STRING *)*fld;
|
||||
utype = str->type & ~V_ASN1_NEG;
|
||||
} else {
|
||||
utype = it->utype;
|
||||
if (utype == V_ASN1_BOOLEAN)
|
||||
str = NULL;
|
||||
else
|
||||
str = (ASN1_STRING *)*fld;
|
||||
}
|
||||
if (utype == V_ASN1_ANY) {
|
||||
ASN1_TYPE *atype = (ASN1_TYPE *)*fld;
|
||||
utype = atype->type;
|
||||
fld = &atype->value.asn1_value;
|
||||
str = (ASN1_STRING *)*fld;
|
||||
if (pctx->flags & ASN1_PCTX_FLAGS_NO_ANY_TYPE)
|
||||
pname = NULL;
|
||||
else
|
||||
pname = ASN1_tag2str(utype);
|
||||
} else {
|
||||
if (pctx->flags & ASN1_PCTX_FLAGS_SHOW_TYPE)
|
||||
pname = ASN1_tag2str(utype);
|
||||
else
|
||||
pname = NULL;
|
||||
}
|
||||
|
||||
if (utype == V_ASN1_NULL) {
|
||||
if (BIO_puts(out, "NULL\n") <= 0)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (pname) {
|
||||
if (BIO_puts(out, pname) <= 0)
|
||||
return 0;
|
||||
if (BIO_puts(out, ":") <= 0)
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch (utype) {
|
||||
case V_ASN1_BOOLEAN:
|
||||
{
|
||||
int boolval = *(int *)fld;
|
||||
if (boolval == -1)
|
||||
boolval = it->size;
|
||||
ret = asn1_print_boolean(out, boolval);
|
||||
}
|
||||
break;
|
||||
|
||||
case V_ASN1_INTEGER:
|
||||
case V_ASN1_ENUMERATED:
|
||||
ret = asn1_print_integer(out, str);
|
||||
break;
|
||||
|
||||
case V_ASN1_UTCTIME:
|
||||
ret = ASN1_UTCTIME_print(out, str);
|
||||
break;
|
||||
|
||||
case V_ASN1_GENERALIZEDTIME:
|
||||
ret = ASN1_GENERALIZEDTIME_print(out, str);
|
||||
break;
|
||||
|
||||
case V_ASN1_OBJECT:
|
||||
ret = asn1_print_oid(out, (const ASN1_OBJECT *)*fld);
|
||||
break;
|
||||
|
||||
case V_ASN1_OCTET_STRING:
|
||||
case V_ASN1_BIT_STRING:
|
||||
ret = asn1_print_obstring(out, str, indent);
|
||||
needlf = 0;
|
||||
break;
|
||||
|
||||
case V_ASN1_SEQUENCE:
|
||||
case V_ASN1_SET:
|
||||
case V_ASN1_OTHER:
|
||||
if (BIO_puts(out, "\n") <= 0)
|
||||
return 0;
|
||||
if (ASN1_parse_dump(out, str->data, str->length, indent, 0) <= 0)
|
||||
ret = 0;
|
||||
needlf = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
ret = ASN1_STRING_print_ex(out, str, pctx->str_flags);
|
||||
|
||||
}
|
||||
if (!ret)
|
||||
return 0;
|
||||
if (needlf && BIO_puts(out, "\n") <= 0)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
65
crypto/asn1/tasn_scn.c
Normal file
65
crypto/asn1/tasn_scn.c
Normal file
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Copyright 2010-2016 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#include <stddef.h>
|
||||
#include "internal/cryptlib.h"
|
||||
#include <openssl/asn1.h>
|
||||
#include <openssl/asn1t.h>
|
||||
#include <openssl/objects.h>
|
||||
#include <openssl/buffer.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/x509v3.h>
|
||||
#include "asn1_locl.h"
|
||||
|
||||
/*
|
||||
* General ASN1 structure recursive scanner: iterate through all fields
|
||||
* passing details to a callback.
|
||||
*/
|
||||
|
||||
ASN1_SCTX *ASN1_SCTX_new(int (*scan_cb) (ASN1_SCTX *ctx))
|
||||
{
|
||||
ASN1_SCTX *ret = OPENSSL_zalloc(sizeof(*ret));
|
||||
|
||||
if (ret == NULL) {
|
||||
ASN1err(ASN1_F_ASN1_SCTX_NEW, ERR_R_MALLOC_FAILURE);
|
||||
return NULL;
|
||||
}
|
||||
ret->scan_cb = scan_cb;
|
||||
return ret;
|
||||
}
|
||||
|
||||
void ASN1_SCTX_free(ASN1_SCTX *p)
|
||||
{
|
||||
OPENSSL_free(p);
|
||||
}
|
||||
|
||||
const ASN1_ITEM *ASN1_SCTX_get_item(ASN1_SCTX *p)
|
||||
{
|
||||
return p->it;
|
||||
}
|
||||
|
||||
const ASN1_TEMPLATE *ASN1_SCTX_get_template(ASN1_SCTX *p)
|
||||
{
|
||||
return p->tt;
|
||||
}
|
||||
|
||||
unsigned long ASN1_SCTX_get_flags(ASN1_SCTX *p)
|
||||
{
|
||||
return p->flags;
|
||||
}
|
||||
|
||||
void ASN1_SCTX_set_app_data(ASN1_SCTX *p, void *data)
|
||||
{
|
||||
p->app_data = data;
|
||||
}
|
||||
|
||||
void *ASN1_SCTX_get_app_data(ASN1_SCTX *p)
|
||||
{
|
||||
return p->app_data;
|
||||
}
|
||||
84
crypto/asn1/tasn_typ.c
Normal file
84
crypto/asn1/tasn_typ.c
Normal file
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <openssl/asn1.h>
|
||||
#include <openssl/asn1t.h>
|
||||
|
||||
/* Declarations for string types */
|
||||
|
||||
#define IMPLEMENT_ASN1_STRING_FUNCTIONS(sname) \
|
||||
IMPLEMENT_ASN1_TYPE(sname) \
|
||||
IMPLEMENT_ASN1_ENCODE_FUNCTIONS_fname(sname, sname, sname) \
|
||||
sname *sname##_new(void) \
|
||||
{ \
|
||||
return ASN1_STRING_type_new(V_##sname); \
|
||||
} \
|
||||
void sname##_free(sname *x) \
|
||||
{ \
|
||||
ASN1_STRING_free(x); \
|
||||
}
|
||||
|
||||
IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_OCTET_STRING)
|
||||
IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_INTEGER)
|
||||
IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_ENUMERATED)
|
||||
IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_BIT_STRING)
|
||||
IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_UTF8STRING)
|
||||
IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_PRINTABLESTRING)
|
||||
IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_T61STRING)
|
||||
IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_IA5STRING)
|
||||
IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_GENERALSTRING)
|
||||
IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_UTCTIME)
|
||||
IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_GENERALIZEDTIME)
|
||||
IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_VISIBLESTRING)
|
||||
IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_UNIVERSALSTRING)
|
||||
IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_BMPSTRING)
|
||||
|
||||
IMPLEMENT_ASN1_TYPE(ASN1_NULL)
|
||||
IMPLEMENT_ASN1_FUNCTIONS(ASN1_NULL)
|
||||
|
||||
IMPLEMENT_ASN1_TYPE(ASN1_OBJECT)
|
||||
|
||||
IMPLEMENT_ASN1_TYPE(ASN1_ANY)
|
||||
|
||||
/* Just swallow an ASN1_SEQUENCE in an ASN1_STRING */
|
||||
IMPLEMENT_ASN1_TYPE(ASN1_SEQUENCE)
|
||||
|
||||
IMPLEMENT_ASN1_FUNCTIONS_fname(ASN1_TYPE, ASN1_ANY, ASN1_TYPE)
|
||||
|
||||
/* Multistring types */
|
||||
|
||||
IMPLEMENT_ASN1_MSTRING(ASN1_PRINTABLE, B_ASN1_PRINTABLE)
|
||||
IMPLEMENT_ASN1_FUNCTIONS_name(ASN1_STRING, ASN1_PRINTABLE)
|
||||
|
||||
IMPLEMENT_ASN1_MSTRING(DISPLAYTEXT, B_ASN1_DISPLAYTEXT)
|
||||
IMPLEMENT_ASN1_FUNCTIONS_name(ASN1_STRING, DISPLAYTEXT)
|
||||
|
||||
IMPLEMENT_ASN1_MSTRING(DIRECTORYSTRING, B_ASN1_DIRECTORYSTRING)
|
||||
IMPLEMENT_ASN1_FUNCTIONS_name(ASN1_STRING, DIRECTORYSTRING)
|
||||
|
||||
/* Three separate BOOLEAN type: normal, DEFAULT TRUE and DEFAULT FALSE */
|
||||
IMPLEMENT_ASN1_TYPE_ex(ASN1_BOOLEAN, ASN1_BOOLEAN, -1)
|
||||
IMPLEMENT_ASN1_TYPE_ex(ASN1_TBOOLEAN, ASN1_BOOLEAN, 1)
|
||||
IMPLEMENT_ASN1_TYPE_ex(ASN1_FBOOLEAN, ASN1_BOOLEAN, 0)
|
||||
|
||||
/* Special, OCTET STRING with indefinite length constructed support */
|
||||
|
||||
IMPLEMENT_ASN1_TYPE_ex(ASN1_OCTET_STRING_NDEF, ASN1_OCTET_STRING, ASN1_TFLG_NDEF)
|
||||
|
||||
ASN1_ITEM_TEMPLATE(ASN1_SEQUENCE_ANY) =
|
||||
ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, ASN1_SEQUENCE_ANY, ASN1_ANY)
|
||||
ASN1_ITEM_TEMPLATE_END(ASN1_SEQUENCE_ANY)
|
||||
|
||||
ASN1_ITEM_TEMPLATE(ASN1_SET_ANY) =
|
||||
ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SET_OF, 0, ASN1_SET_ANY, ASN1_ANY)
|
||||
ASN1_ITEM_TEMPLATE_END(ASN1_SET_ANY)
|
||||
|
||||
IMPLEMENT_ASN1_ENCODE_FUNCTIONS_const_fname(ASN1_SEQUENCE_ANY, ASN1_SEQUENCE_ANY, ASN1_SEQUENCE_ANY)
|
||||
IMPLEMENT_ASN1_ENCODE_FUNCTIONS_const_fname(ASN1_SEQUENCE_ANY, ASN1_SET_ANY, ASN1_SET_ANY)
|
||||
253
crypto/asn1/tasn_utl.c
Normal file
253
crypto/asn1/tasn_utl.c
Normal file
@@ -0,0 +1,253 @@
|
||||
/*
|
||||
* Copyright 2000-2018 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
#include "internal/cryptlib.h"
|
||||
#include "internal/refcount.h"
|
||||
#include <openssl/asn1.h>
|
||||
#include <openssl/asn1t.h>
|
||||
#include <openssl/objects.h>
|
||||
#include <openssl/err.h>
|
||||
#include "asn1_locl.h"
|
||||
|
||||
/* Utility functions for manipulating fields and offsets */
|
||||
|
||||
/* Add 'offset' to 'addr' */
|
||||
#define offset2ptr(addr, offset) (void *)(((char *) addr) + offset)
|
||||
|
||||
/*
|
||||
* Given an ASN1_ITEM CHOICE type return the selector value
|
||||
*/
|
||||
|
||||
int asn1_get_choice_selector(ASN1_VALUE **pval, const ASN1_ITEM *it)
|
||||
{
|
||||
int *sel = offset2ptr(*pval, it->utype);
|
||||
return *sel;
|
||||
}
|
||||
|
||||
/*
|
||||
* Given an ASN1_ITEM CHOICE type set the selector value, return old value.
|
||||
*/
|
||||
|
||||
int asn1_set_choice_selector(ASN1_VALUE **pval, int value,
|
||||
const ASN1_ITEM *it)
|
||||
{
|
||||
int *sel, ret;
|
||||
sel = offset2ptr(*pval, it->utype);
|
||||
ret = *sel;
|
||||
*sel = value;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Do atomic reference counting. The value 'op' decides what to do.
|
||||
* If it is +1 then the count is incremented.
|
||||
* If |op| is 0, lock is initialised and count is set to 1.
|
||||
* If |op| is -1, count is decremented and the return value is the current
|
||||
* reference count or 0 if no reference count is active.
|
||||
* It returns -1 on initialisation error.
|
||||
* Used by ASN1_SEQUENCE construct of X509, X509_REQ, X509_CRL objects
|
||||
*/
|
||||
int asn1_do_lock(ASN1_VALUE **pval, int op, const ASN1_ITEM *it)
|
||||
{
|
||||
const ASN1_AUX *aux;
|
||||
CRYPTO_REF_COUNT *lck;
|
||||
CRYPTO_RWLOCK **lock;
|
||||
int ret = -1;
|
||||
|
||||
if ((it->itype != ASN1_ITYPE_SEQUENCE)
|
||||
&& (it->itype != ASN1_ITYPE_NDEF_SEQUENCE))
|
||||
return 0;
|
||||
aux = it->funcs;
|
||||
if (!aux || !(aux->flags & ASN1_AFLG_REFCOUNT))
|
||||
return 0;
|
||||
lck = offset2ptr(*pval, aux->ref_offset);
|
||||
lock = offset2ptr(*pval, aux->ref_lock);
|
||||
|
||||
switch (op) {
|
||||
case 0:
|
||||
*lck = ret = 1;
|
||||
*lock = CRYPTO_THREAD_lock_new();
|
||||
if (*lock == NULL) {
|
||||
ASN1err(ASN1_F_ASN1_DO_LOCK, ERR_R_MALLOC_FAILURE);
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
if (!CRYPTO_UP_REF(lck, &ret, *lock))
|
||||
return -1;
|
||||
break;
|
||||
case -1:
|
||||
if (!CRYPTO_DOWN_REF(lck, &ret, *lock))
|
||||
return -1; /* failed */
|
||||
#ifdef REF_PRINT
|
||||
fprintf(stderr, "%p:%4d:%s\n", it, ret, it->sname);
|
||||
#endif
|
||||
REF_ASSERT_ISNT(ret < 0);
|
||||
if (ret == 0) {
|
||||
CRYPTO_THREAD_lock_free(*lock);
|
||||
*lock = NULL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ASN1_ENCODING *asn1_get_enc_ptr(ASN1_VALUE **pval, const ASN1_ITEM *it)
|
||||
{
|
||||
const ASN1_AUX *aux;
|
||||
if (!pval || !*pval)
|
||||
return NULL;
|
||||
aux = it->funcs;
|
||||
if (!aux || !(aux->flags & ASN1_AFLG_ENCODING))
|
||||
return NULL;
|
||||
return offset2ptr(*pval, aux->enc_offset);
|
||||
}
|
||||
|
||||
void asn1_enc_init(ASN1_VALUE **pval, const ASN1_ITEM *it)
|
||||
{
|
||||
ASN1_ENCODING *enc;
|
||||
enc = asn1_get_enc_ptr(pval, it);
|
||||
if (enc) {
|
||||
enc->enc = NULL;
|
||||
enc->len = 0;
|
||||
enc->modified = 1;
|
||||
}
|
||||
}
|
||||
|
||||
void asn1_enc_free(ASN1_VALUE **pval, const ASN1_ITEM *it)
|
||||
{
|
||||
ASN1_ENCODING *enc;
|
||||
enc = asn1_get_enc_ptr(pval, it);
|
||||
if (enc) {
|
||||
OPENSSL_free(enc->enc);
|
||||
enc->enc = NULL;
|
||||
enc->len = 0;
|
||||
enc->modified = 1;
|
||||
}
|
||||
}
|
||||
|
||||
int asn1_enc_save(ASN1_VALUE **pval, const unsigned char *in, int inlen,
|
||||
const ASN1_ITEM *it)
|
||||
{
|
||||
ASN1_ENCODING *enc;
|
||||
enc = asn1_get_enc_ptr(pval, it);
|
||||
if (!enc)
|
||||
return 1;
|
||||
|
||||
OPENSSL_free(enc->enc);
|
||||
if ((enc->enc = OPENSSL_malloc(inlen)) == NULL) {
|
||||
ASN1err(ASN1_F_ASN1_ENC_SAVE, ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
memcpy(enc->enc, in, inlen);
|
||||
enc->len = inlen;
|
||||
enc->modified = 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int asn1_enc_restore(int *len, unsigned char **out, ASN1_VALUE **pval,
|
||||
const ASN1_ITEM *it)
|
||||
{
|
||||
ASN1_ENCODING *enc;
|
||||
enc = asn1_get_enc_ptr(pval, it);
|
||||
if (!enc || enc->modified)
|
||||
return 0;
|
||||
if (out) {
|
||||
memcpy(*out, enc->enc, enc->len);
|
||||
*out += enc->len;
|
||||
}
|
||||
if (len)
|
||||
*len = enc->len;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Given an ASN1_TEMPLATE get a pointer to a field */
|
||||
ASN1_VALUE **asn1_get_field_ptr(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt)
|
||||
{
|
||||
ASN1_VALUE **pvaltmp;
|
||||
pvaltmp = offset2ptr(*pval, tt->offset);
|
||||
/*
|
||||
* NOTE for BOOLEAN types the field is just a plain int so we can't
|
||||
* return int **, so settle for (int *).
|
||||
*/
|
||||
return pvaltmp;
|
||||
}
|
||||
|
||||
/*
|
||||
* Handle ANY DEFINED BY template, find the selector, look up the relevant
|
||||
* ASN1_TEMPLATE in the table and return it.
|
||||
*/
|
||||
|
||||
const ASN1_TEMPLATE *asn1_do_adb(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt,
|
||||
int nullerr)
|
||||
{
|
||||
const ASN1_ADB *adb;
|
||||
const ASN1_ADB_TABLE *atbl;
|
||||
long selector;
|
||||
ASN1_VALUE **sfld;
|
||||
int i;
|
||||
if (!(tt->flags & ASN1_TFLG_ADB_MASK))
|
||||
return tt;
|
||||
|
||||
/* Else ANY DEFINED BY ... get the table */
|
||||
adb = ASN1_ADB_ptr(tt->item);
|
||||
|
||||
/* Get the selector field */
|
||||
sfld = offset2ptr(*pval, adb->offset);
|
||||
|
||||
/* Check if NULL */
|
||||
if (*sfld == NULL) {
|
||||
if (!adb->null_tt)
|
||||
goto err;
|
||||
return adb->null_tt;
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert type to a long: NB: don't check for NID_undef here because it
|
||||
* might be a legitimate value in the table
|
||||
*/
|
||||
if (tt->flags & ASN1_TFLG_ADB_OID)
|
||||
selector = OBJ_obj2nid((ASN1_OBJECT *)*sfld);
|
||||
else
|
||||
selector = ASN1_INTEGER_get((ASN1_INTEGER *)*sfld);
|
||||
|
||||
/* Let application callback translate value */
|
||||
if (adb->adb_cb != NULL && adb->adb_cb(&selector) == 0) {
|
||||
ASN1err(ASN1_F_ASN1_DO_ADB, ASN1_R_UNSUPPORTED_ANY_DEFINED_BY_TYPE);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Try to find matching entry in table Maybe should check application
|
||||
* types first to allow application override? Might also be useful to
|
||||
* have a flag which indicates table is sorted and we can do a binary
|
||||
* search. For now stick to a linear search.
|
||||
*/
|
||||
|
||||
for (atbl = adb->tbl, i = 0; i < adb->tblcount; i++, atbl++)
|
||||
if (atbl->value == selector)
|
||||
return &atbl->tt;
|
||||
|
||||
/* FIXME: need to search application table too */
|
||||
|
||||
/* No match, return default type */
|
||||
if (!adb->default_tt)
|
||||
goto err;
|
||||
return adb->default_tt;
|
||||
|
||||
err:
|
||||
/* FIXME: should log the value or OID of unsupported type */
|
||||
if (nullerr)
|
||||
ASN1err(ASN1_F_ASN1_DO_ADB, ASN1_R_UNSUPPORTED_ANY_DEFINED_BY_TYPE);
|
||||
return NULL;
|
||||
}
|
||||
61
crypto/asn1/tbl_standard.h
Normal file
61
crypto/asn1/tbl_standard.h
Normal file
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
/* size limits: this stuff is taken straight from RFC3280 */
|
||||
|
||||
#define ub_name 32768
|
||||
#define ub_common_name 64
|
||||
#define ub_locality_name 128
|
||||
#define ub_state_name 128
|
||||
#define ub_organization_name 64
|
||||
#define ub_organization_unit_name 64
|
||||
#define ub_title 64
|
||||
#define ub_email_address 128
|
||||
#define ub_serial_number 64
|
||||
|
||||
/* From RFC4524 */
|
||||
|
||||
#define ub_rfc822_mailbox 256
|
||||
|
||||
/* This table must be kept in NID order */
|
||||
|
||||
static const ASN1_STRING_TABLE tbl_standard[] = {
|
||||
{NID_commonName, 1, ub_common_name, DIRSTRING_TYPE, 0},
|
||||
{NID_countryName, 2, 2, B_ASN1_PRINTABLESTRING, STABLE_NO_MASK},
|
||||
{NID_localityName, 1, ub_locality_name, DIRSTRING_TYPE, 0},
|
||||
{NID_stateOrProvinceName, 1, ub_state_name, DIRSTRING_TYPE, 0},
|
||||
{NID_organizationName, 1, ub_organization_name, DIRSTRING_TYPE, 0},
|
||||
{NID_organizationalUnitName, 1, ub_organization_unit_name, DIRSTRING_TYPE,
|
||||
0},
|
||||
{NID_pkcs9_emailAddress, 1, ub_email_address, B_ASN1_IA5STRING,
|
||||
STABLE_NO_MASK},
|
||||
{NID_pkcs9_unstructuredName, 1, -1, PKCS9STRING_TYPE, 0},
|
||||
{NID_pkcs9_challengePassword, 1, -1, PKCS9STRING_TYPE, 0},
|
||||
{NID_pkcs9_unstructuredAddress, 1, -1, DIRSTRING_TYPE, 0},
|
||||
{NID_givenName, 1, ub_name, DIRSTRING_TYPE, 0},
|
||||
{NID_surname, 1, ub_name, DIRSTRING_TYPE, 0},
|
||||
{NID_initials, 1, ub_name, DIRSTRING_TYPE, 0},
|
||||
{NID_serialNumber, 1, ub_serial_number, B_ASN1_PRINTABLESTRING,
|
||||
STABLE_NO_MASK},
|
||||
{NID_friendlyName, -1, -1, B_ASN1_BMPSTRING, STABLE_NO_MASK},
|
||||
{NID_name, 1, ub_name, DIRSTRING_TYPE, 0},
|
||||
{NID_dnQualifier, -1, -1, B_ASN1_PRINTABLESTRING, STABLE_NO_MASK},
|
||||
{NID_domainComponent, 1, -1, B_ASN1_IA5STRING, STABLE_NO_MASK},
|
||||
{NID_ms_csp_name, -1, -1, B_ASN1_BMPSTRING, STABLE_NO_MASK},
|
||||
{NID_rfc822Mailbox, 1, ub_rfc822_mailbox, B_ASN1_IA5STRING,
|
||||
STABLE_NO_MASK},
|
||||
{NID_jurisdictionCountryName, 2, 2, B_ASN1_PRINTABLESTRING, STABLE_NO_MASK},
|
||||
{NID_INN, 1, 12, B_ASN1_NUMERICSTRING, STABLE_NO_MASK},
|
||||
{NID_OGRN, 1, 13, B_ASN1_NUMERICSTRING, STABLE_NO_MASK},
|
||||
{NID_SNILS, 1, 11, B_ASN1_NUMERICSTRING, STABLE_NO_MASK},
|
||||
{NID_countryCode3c, 3, 3, B_ASN1_PRINTABLESTRING, STABLE_NO_MASK},
|
||||
{NID_countryCode3n, 3, 3, B_ASN1_NUMERICSTRING, STABLE_NO_MASK},
|
||||
{NID_dnsName, 0, -1, B_ASN1_UTF8STRING, STABLE_NO_MASK}
|
||||
};
|
||||
|
||||
94
crypto/asn1/x_algor.c
Normal file
94
crypto/asn1/x_algor.c
Normal file
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
* Copyright 1998-2016 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#include <stddef.h>
|
||||
#include <openssl/x509.h>
|
||||
#include <openssl/asn1.h>
|
||||
#include <openssl/asn1t.h>
|
||||
#include "internal/evp_int.h"
|
||||
|
||||
ASN1_SEQUENCE(X509_ALGOR) = {
|
||||
ASN1_SIMPLE(X509_ALGOR, algorithm, ASN1_OBJECT),
|
||||
ASN1_OPT(X509_ALGOR, parameter, ASN1_ANY)
|
||||
} ASN1_SEQUENCE_END(X509_ALGOR)
|
||||
|
||||
ASN1_ITEM_TEMPLATE(X509_ALGORS) =
|
||||
ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, algorithms, X509_ALGOR)
|
||||
ASN1_ITEM_TEMPLATE_END(X509_ALGORS)
|
||||
|
||||
IMPLEMENT_ASN1_FUNCTIONS(X509_ALGOR)
|
||||
IMPLEMENT_ASN1_ENCODE_FUNCTIONS_fname(X509_ALGORS, X509_ALGORS, X509_ALGORS)
|
||||
IMPLEMENT_ASN1_DUP_FUNCTION(X509_ALGOR)
|
||||
|
||||
int X509_ALGOR_set0(X509_ALGOR *alg, ASN1_OBJECT *aobj, int ptype, void *pval)
|
||||
{
|
||||
if (alg == NULL)
|
||||
return 0;
|
||||
|
||||
if (ptype != V_ASN1_UNDEF) {
|
||||
if (alg->parameter == NULL)
|
||||
alg->parameter = ASN1_TYPE_new();
|
||||
if (alg->parameter == NULL)
|
||||
return 0;
|
||||
}
|
||||
|
||||
ASN1_OBJECT_free(alg->algorithm);
|
||||
alg->algorithm = aobj;
|
||||
|
||||
if (ptype == 0)
|
||||
return 1;
|
||||
if (ptype == V_ASN1_UNDEF) {
|
||||
ASN1_TYPE_free(alg->parameter);
|
||||
alg->parameter = NULL;
|
||||
} else
|
||||
ASN1_TYPE_set(alg->parameter, ptype, pval);
|
||||
return 1;
|
||||
}
|
||||
|
||||
void X509_ALGOR_get0(const ASN1_OBJECT **paobj, int *pptype,
|
||||
const void **ppval, const X509_ALGOR *algor)
|
||||
{
|
||||
if (paobj)
|
||||
*paobj = algor->algorithm;
|
||||
if (pptype) {
|
||||
if (algor->parameter == NULL) {
|
||||
*pptype = V_ASN1_UNDEF;
|
||||
return;
|
||||
} else
|
||||
*pptype = algor->parameter->type;
|
||||
if (ppval)
|
||||
*ppval = algor->parameter->value.ptr;
|
||||
}
|
||||
}
|
||||
|
||||
/* Set up an X509_ALGOR DigestAlgorithmIdentifier from an EVP_MD */
|
||||
|
||||
void X509_ALGOR_set_md(X509_ALGOR *alg, const EVP_MD *md)
|
||||
{
|
||||
int param_type;
|
||||
|
||||
if (md->flags & EVP_MD_FLAG_DIGALGID_ABSENT)
|
||||
param_type = V_ASN1_UNDEF;
|
||||
else
|
||||
param_type = V_ASN1_NULL;
|
||||
|
||||
X509_ALGOR_set0(alg, OBJ_nid2obj(EVP_MD_type(md)), param_type, NULL);
|
||||
|
||||
}
|
||||
|
||||
int X509_ALGOR_cmp(const X509_ALGOR *a, const X509_ALGOR *b)
|
||||
{
|
||||
int rv;
|
||||
rv = OBJ_cmp(a->algorithm, b->algorithm);
|
||||
if (rv)
|
||||
return rv;
|
||||
if (!a->parameter && !b->parameter)
|
||||
return 0;
|
||||
return ASN1_TYPE_cmp(a->parameter, b->parameter);
|
||||
}
|
||||
146
crypto/asn1/x_bignum.c
Normal file
146
crypto/asn1/x_bignum.c
Normal file
@@ -0,0 +1,146 @@
|
||||
/*
|
||||
* Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "internal/cryptlib.h"
|
||||
#include <openssl/asn1t.h>
|
||||
#include <openssl/bn.h>
|
||||
|
||||
/*
|
||||
* Custom primitive type for BIGNUM handling. This reads in an ASN1_INTEGER
|
||||
* as a BIGNUM directly. Currently it ignores the sign which isn't a problem
|
||||
* since all BIGNUMs used are non negative and anything that looks negative
|
||||
* is normally due to an encoding error.
|
||||
*/
|
||||
|
||||
#define BN_SENSITIVE 1
|
||||
|
||||
static int bn_new(ASN1_VALUE **pval, const ASN1_ITEM *it);
|
||||
static int bn_secure_new(ASN1_VALUE **pval, const ASN1_ITEM *it);
|
||||
static void bn_free(ASN1_VALUE **pval, const ASN1_ITEM *it);
|
||||
|
||||
static int bn_i2c(ASN1_VALUE **pval, unsigned char *cont, int *putype,
|
||||
const ASN1_ITEM *it);
|
||||
static int bn_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len,
|
||||
int utype, char *free_cont, const ASN1_ITEM *it);
|
||||
static int bn_secure_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len,
|
||||
int utype, char *free_cont, const ASN1_ITEM *it);
|
||||
static int bn_print(BIO *out, ASN1_VALUE **pval, const ASN1_ITEM *it,
|
||||
int indent, const ASN1_PCTX *pctx);
|
||||
|
||||
static ASN1_PRIMITIVE_FUNCS bignum_pf = {
|
||||
NULL, 0,
|
||||
bn_new,
|
||||
bn_free,
|
||||
0,
|
||||
bn_c2i,
|
||||
bn_i2c,
|
||||
bn_print
|
||||
};
|
||||
|
||||
static ASN1_PRIMITIVE_FUNCS cbignum_pf = {
|
||||
NULL, 0,
|
||||
bn_secure_new,
|
||||
bn_free,
|
||||
0,
|
||||
bn_secure_c2i,
|
||||
bn_i2c,
|
||||
bn_print
|
||||
};
|
||||
|
||||
ASN1_ITEM_start(BIGNUM)
|
||||
ASN1_ITYPE_PRIMITIVE, V_ASN1_INTEGER, NULL, 0, &bignum_pf, 0, "BIGNUM"
|
||||
ASN1_ITEM_end(BIGNUM)
|
||||
|
||||
ASN1_ITEM_start(CBIGNUM)
|
||||
ASN1_ITYPE_PRIMITIVE, V_ASN1_INTEGER, NULL, 0, &cbignum_pf, BN_SENSITIVE, "CBIGNUM"
|
||||
ASN1_ITEM_end(CBIGNUM)
|
||||
|
||||
static int bn_new(ASN1_VALUE **pval, const ASN1_ITEM *it)
|
||||
{
|
||||
*pval = (ASN1_VALUE *)BN_new();
|
||||
if (*pval != NULL)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bn_secure_new(ASN1_VALUE **pval, const ASN1_ITEM *it)
|
||||
{
|
||||
*pval = (ASN1_VALUE *)BN_secure_new();
|
||||
if (*pval != NULL)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void bn_free(ASN1_VALUE **pval, const ASN1_ITEM *it)
|
||||
{
|
||||
if (!*pval)
|
||||
return;
|
||||
if (it->size & BN_SENSITIVE)
|
||||
BN_clear_free((BIGNUM *)*pval);
|
||||
else
|
||||
BN_free((BIGNUM *)*pval);
|
||||
*pval = NULL;
|
||||
}
|
||||
|
||||
static int bn_i2c(ASN1_VALUE **pval, unsigned char *cont, int *putype,
|
||||
const ASN1_ITEM *it)
|
||||
{
|
||||
BIGNUM *bn;
|
||||
int pad;
|
||||
if (!*pval)
|
||||
return -1;
|
||||
bn = (BIGNUM *)*pval;
|
||||
/* If MSB set in an octet we need a padding byte */
|
||||
if (BN_num_bits(bn) & 0x7)
|
||||
pad = 0;
|
||||
else
|
||||
pad = 1;
|
||||
if (cont) {
|
||||
if (pad)
|
||||
*cont++ = 0;
|
||||
BN_bn2bin(bn, cont);
|
||||
}
|
||||
return pad + BN_num_bytes(bn);
|
||||
}
|
||||
|
||||
static int bn_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len,
|
||||
int utype, char *free_cont, const ASN1_ITEM *it)
|
||||
{
|
||||
BIGNUM *bn;
|
||||
|
||||
if (*pval == NULL && !bn_new(pval, it))
|
||||
return 0;
|
||||
bn = (BIGNUM *)*pval;
|
||||
if (!BN_bin2bn(cont, len, bn)) {
|
||||
bn_free(pval, it);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int bn_secure_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len,
|
||||
int utype, char *free_cont, const ASN1_ITEM *it)
|
||||
{
|
||||
if (!*pval)
|
||||
bn_secure_new(pval, it);
|
||||
return bn_c2i(pval, cont, len, utype, free_cont, it);
|
||||
}
|
||||
|
||||
static int bn_print(BIO *out, ASN1_VALUE **pval, const ASN1_ITEM *it,
|
||||
int indent, const ASN1_PCTX *pctx)
|
||||
{
|
||||
if (!BN_print(out, *(BIGNUM **)pval))
|
||||
return 0;
|
||||
if (BIO_puts(out, "\n") <= 0)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
39
crypto/asn1/x_info.c
Normal file
39
crypto/asn1/x_info.c
Normal file
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "internal/cryptlib.h"
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/asn1.h>
|
||||
#include <openssl/x509.h>
|
||||
|
||||
X509_INFO *X509_INFO_new(void)
|
||||
{
|
||||
X509_INFO *ret;
|
||||
|
||||
ret = OPENSSL_zalloc(sizeof(*ret));
|
||||
if (ret == NULL) {
|
||||
ASN1err(ASN1_F_X509_INFO_NEW, ERR_R_MALLOC_FAILURE);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void X509_INFO_free(X509_INFO *x)
|
||||
{
|
||||
if (x == NULL)
|
||||
return;
|
||||
|
||||
X509_free(x->x509);
|
||||
X509_CRL_free(x->crl);
|
||||
X509_PKEY_free(x->x_pkey);
|
||||
OPENSSL_free(x->enc_data);
|
||||
OPENSSL_free(x);
|
||||
}
|
||||
291
crypto/asn1/x_int64.c
Normal file
291
crypto/asn1/x_int64.c
Normal file
@@ -0,0 +1,291 @@
|
||||
/*
|
||||
* Copyright 2017-2018 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "internal/cryptlib.h"
|
||||
#include "internal/numbers.h"
|
||||
#include <openssl/asn1t.h>
|
||||
#include <openssl/bn.h>
|
||||
#include "asn1_locl.h"
|
||||
|
||||
/*
|
||||
* Custom primitive types for handling int32_t, int64_t, uint32_t, uint64_t.
|
||||
* This converts between an ASN1_INTEGER and those types directly.
|
||||
* This is preferred to using the LONG / ZLONG primitives.
|
||||
*/
|
||||
|
||||
/*
|
||||
* We abuse the ASN1_ITEM fields |size| as a flags field
|
||||
*/
|
||||
#define INTxx_FLAG_ZERO_DEFAULT (1<<0)
|
||||
#define INTxx_FLAG_SIGNED (1<<1)
|
||||
|
||||
static int uint64_new(ASN1_VALUE **pval, const ASN1_ITEM *it)
|
||||
{
|
||||
if ((*pval = (ASN1_VALUE *)OPENSSL_zalloc(sizeof(uint64_t))) == NULL) {
|
||||
ASN1err(ASN1_F_UINT64_NEW, ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void uint64_free(ASN1_VALUE **pval, const ASN1_ITEM *it)
|
||||
{
|
||||
OPENSSL_free(*pval);
|
||||
*pval = NULL;
|
||||
}
|
||||
|
||||
static void uint64_clear(ASN1_VALUE **pval, const ASN1_ITEM *it)
|
||||
{
|
||||
**(uint64_t **)pval = 0;
|
||||
}
|
||||
|
||||
static int uint64_i2c(ASN1_VALUE **pval, unsigned char *cont, int *putype,
|
||||
const ASN1_ITEM *it)
|
||||
{
|
||||
uint64_t utmp;
|
||||
int neg = 0;
|
||||
/* this exists to bypass broken gcc optimization */
|
||||
char *cp = (char *)*pval;
|
||||
|
||||
/* use memcpy, because we may not be uint64_t aligned */
|
||||
memcpy(&utmp, cp, sizeof(utmp));
|
||||
|
||||
if ((it->size & INTxx_FLAG_ZERO_DEFAULT) == INTxx_FLAG_ZERO_DEFAULT
|
||||
&& utmp == 0)
|
||||
return -1;
|
||||
if ((it->size & INTxx_FLAG_SIGNED) == INTxx_FLAG_SIGNED
|
||||
&& (int64_t)utmp < 0) {
|
||||
/* i2c_uint64_int() assumes positive values */
|
||||
utmp = 0 - utmp;
|
||||
neg = 1;
|
||||
}
|
||||
|
||||
return i2c_uint64_int(cont, utmp, neg);
|
||||
}
|
||||
|
||||
static int uint64_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len,
|
||||
int utype, char *free_cont, const ASN1_ITEM *it)
|
||||
{
|
||||
uint64_t utmp = 0;
|
||||
char *cp;
|
||||
int neg = 0;
|
||||
|
||||
if (*pval == NULL && !uint64_new(pval, it))
|
||||
return 0;
|
||||
|
||||
cp = (char *)*pval;
|
||||
|
||||
/*
|
||||
* Strictly speaking, zero length is malformed. However, long_c2i
|
||||
* (x_long.c) encodes 0 as a zero length INTEGER (wrongly, of course),
|
||||
* so for the sake of backward compatibility, we still decode zero
|
||||
* length INTEGERs as the number zero.
|
||||
*/
|
||||
if (len == 0)
|
||||
goto long_compat;
|
||||
|
||||
if (!c2i_uint64_int(&utmp, &neg, &cont, len))
|
||||
return 0;
|
||||
if ((it->size & INTxx_FLAG_SIGNED) == 0 && neg) {
|
||||
ASN1err(ASN1_F_UINT64_C2I, ASN1_R_ILLEGAL_NEGATIVE_VALUE);
|
||||
return 0;
|
||||
}
|
||||
if ((it->size & INTxx_FLAG_SIGNED) == INTxx_FLAG_SIGNED
|
||||
&& !neg && utmp > INT64_MAX) {
|
||||
ASN1err(ASN1_F_UINT64_C2I, ASN1_R_TOO_LARGE);
|
||||
return 0;
|
||||
}
|
||||
if (neg)
|
||||
/* c2i_uint64_int() returns positive values */
|
||||
utmp = 0 - utmp;
|
||||
|
||||
long_compat:
|
||||
memcpy(cp, &utmp, sizeof(utmp));
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int uint64_print(BIO *out, ASN1_VALUE **pval, const ASN1_ITEM *it,
|
||||
int indent, const ASN1_PCTX *pctx)
|
||||
{
|
||||
if ((it->size & INTxx_FLAG_SIGNED) == INTxx_FLAG_SIGNED)
|
||||
return BIO_printf(out, "%jd\n", **(int64_t **)pval);
|
||||
return BIO_printf(out, "%ju\n", **(uint64_t **)pval);
|
||||
}
|
||||
|
||||
/* 32-bit variants */
|
||||
|
||||
static int uint32_new(ASN1_VALUE **pval, const ASN1_ITEM *it)
|
||||
{
|
||||
if ((*pval = (ASN1_VALUE *)OPENSSL_zalloc(sizeof(uint32_t))) == NULL) {
|
||||
ASN1err(ASN1_F_UINT32_NEW, ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void uint32_free(ASN1_VALUE **pval, const ASN1_ITEM *it)
|
||||
{
|
||||
OPENSSL_free(*pval);
|
||||
*pval = NULL;
|
||||
}
|
||||
|
||||
static void uint32_clear(ASN1_VALUE **pval, const ASN1_ITEM *it)
|
||||
{
|
||||
**(uint32_t **)pval = 0;
|
||||
}
|
||||
|
||||
static int uint32_i2c(ASN1_VALUE **pval, unsigned char *cont, int *putype,
|
||||
const ASN1_ITEM *it)
|
||||
{
|
||||
uint32_t utmp;
|
||||
int neg = 0;
|
||||
/* this exists to bypass broken gcc optimization */
|
||||
char *cp = (char *)*pval;
|
||||
|
||||
/* use memcpy, because we may not be uint32_t aligned */
|
||||
memcpy(&utmp, cp, sizeof(utmp));
|
||||
|
||||
if ((it->size & INTxx_FLAG_ZERO_DEFAULT) == INTxx_FLAG_ZERO_DEFAULT
|
||||
&& utmp == 0)
|
||||
return -1;
|
||||
if ((it->size & INTxx_FLAG_SIGNED) == INTxx_FLAG_SIGNED
|
||||
&& (int32_t)utmp < 0) {
|
||||
/* i2c_uint64_int() assumes positive values */
|
||||
utmp = 0 - utmp;
|
||||
neg = 1;
|
||||
}
|
||||
|
||||
return i2c_uint64_int(cont, (uint64_t)utmp, neg);
|
||||
}
|
||||
|
||||
/*
|
||||
* Absolute value of INT32_MIN: we can't just use -INT32_MIN as it produces
|
||||
* overflow warnings.
|
||||
*/
|
||||
|
||||
#define ABS_INT32_MIN ((uint32_t)INT32_MAX + 1)
|
||||
|
||||
static int uint32_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len,
|
||||
int utype, char *free_cont, const ASN1_ITEM *it)
|
||||
{
|
||||
uint64_t utmp = 0;
|
||||
uint32_t utmp2 = 0;
|
||||
char *cp;
|
||||
int neg = 0;
|
||||
|
||||
if (*pval == NULL && !uint64_new(pval, it))
|
||||
return 0;
|
||||
|
||||
cp = (char *)*pval;
|
||||
|
||||
/*
|
||||
* Strictly speaking, zero length is malformed. However, long_c2i
|
||||
* (x_long.c) encodes 0 as a zero length INTEGER (wrongly, of course),
|
||||
* so for the sake of backward compatibility, we still decode zero
|
||||
* length INTEGERs as the number zero.
|
||||
*/
|
||||
if (len == 0)
|
||||
goto long_compat;
|
||||
|
||||
if (!c2i_uint64_int(&utmp, &neg, &cont, len))
|
||||
return 0;
|
||||
if ((it->size & INTxx_FLAG_SIGNED) == 0 && neg) {
|
||||
ASN1err(ASN1_F_UINT32_C2I, ASN1_R_ILLEGAL_NEGATIVE_VALUE);
|
||||
return 0;
|
||||
}
|
||||
if (neg) {
|
||||
if (utmp > ABS_INT32_MIN) {
|
||||
ASN1err(ASN1_F_UINT32_C2I, ASN1_R_TOO_SMALL);
|
||||
return 0;
|
||||
}
|
||||
utmp = 0 - utmp;
|
||||
} else {
|
||||
if (((it->size & INTxx_FLAG_SIGNED) != 0 && utmp > INT32_MAX)
|
||||
|| ((it->size & INTxx_FLAG_SIGNED) == 0 && utmp > UINT32_MAX)) {
|
||||
ASN1err(ASN1_F_UINT32_C2I, ASN1_R_TOO_LARGE);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
long_compat:
|
||||
utmp2 = (uint32_t)utmp;
|
||||
memcpy(cp, &utmp2, sizeof(utmp2));
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int uint32_print(BIO *out, ASN1_VALUE **pval, const ASN1_ITEM *it,
|
||||
int indent, const ASN1_PCTX *pctx)
|
||||
{
|
||||
if ((it->size & INTxx_FLAG_SIGNED) == INTxx_FLAG_SIGNED)
|
||||
return BIO_printf(out, "%d\n", **(int32_t **)pval);
|
||||
return BIO_printf(out, "%u\n", **(uint32_t **)pval);
|
||||
}
|
||||
|
||||
|
||||
/* Define the primitives themselves */
|
||||
|
||||
static ASN1_PRIMITIVE_FUNCS uint32_pf = {
|
||||
NULL, 0,
|
||||
uint32_new,
|
||||
uint32_free,
|
||||
uint32_clear,
|
||||
uint32_c2i,
|
||||
uint32_i2c,
|
||||
uint32_print
|
||||
};
|
||||
|
||||
static ASN1_PRIMITIVE_FUNCS uint64_pf = {
|
||||
NULL, 0,
|
||||
uint64_new,
|
||||
uint64_free,
|
||||
uint64_clear,
|
||||
uint64_c2i,
|
||||
uint64_i2c,
|
||||
uint64_print
|
||||
};
|
||||
|
||||
ASN1_ITEM_start(INT32)
|
||||
ASN1_ITYPE_PRIMITIVE, V_ASN1_INTEGER, NULL, 0, &uint32_pf,
|
||||
INTxx_FLAG_SIGNED, "INT32"
|
||||
ASN1_ITEM_end(INT32)
|
||||
|
||||
ASN1_ITEM_start(UINT32)
|
||||
ASN1_ITYPE_PRIMITIVE, V_ASN1_INTEGER, NULL, 0, &uint32_pf, 0, "UINT32"
|
||||
ASN1_ITEM_end(UINT32)
|
||||
|
||||
ASN1_ITEM_start(INT64)
|
||||
ASN1_ITYPE_PRIMITIVE, V_ASN1_INTEGER, NULL, 0, &uint64_pf,
|
||||
INTxx_FLAG_SIGNED, "INT64"
|
||||
ASN1_ITEM_end(INT64)
|
||||
|
||||
ASN1_ITEM_start(UINT64)
|
||||
ASN1_ITYPE_PRIMITIVE, V_ASN1_INTEGER, NULL, 0, &uint64_pf, 0, "UINT64"
|
||||
ASN1_ITEM_end(UINT64)
|
||||
|
||||
ASN1_ITEM_start(ZINT32)
|
||||
ASN1_ITYPE_PRIMITIVE, V_ASN1_INTEGER, NULL, 0, &uint32_pf,
|
||||
INTxx_FLAG_ZERO_DEFAULT|INTxx_FLAG_SIGNED, "ZINT32"
|
||||
ASN1_ITEM_end(ZINT32)
|
||||
|
||||
ASN1_ITEM_start(ZUINT32)
|
||||
ASN1_ITYPE_PRIMITIVE, V_ASN1_INTEGER, NULL, 0, &uint32_pf,
|
||||
INTxx_FLAG_ZERO_DEFAULT, "ZUINT32"
|
||||
ASN1_ITEM_end(ZUINT32)
|
||||
|
||||
ASN1_ITEM_start(ZINT64)
|
||||
ASN1_ITYPE_PRIMITIVE, V_ASN1_INTEGER, NULL, 0, &uint64_pf,
|
||||
INTxx_FLAG_ZERO_DEFAULT|INTxx_FLAG_SIGNED, "ZINT64"
|
||||
ASN1_ITEM_end(ZINT64)
|
||||
|
||||
ASN1_ITEM_start(ZUINT64)
|
||||
ASN1_ITYPE_PRIMITIVE, V_ASN1_INTEGER, NULL, 0, &uint64_pf,
|
||||
INTxx_FLAG_ZERO_DEFAULT, "ZUINT64"
|
||||
ASN1_ITEM_end(ZUINT64)
|
||||
|
||||
201
crypto/asn1/x_long.c
Normal file
201
crypto/asn1/x_long.c
Normal file
@@ -0,0 +1,201 @@
|
||||
/*
|
||||
* Copyright 2000-2017 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "internal/cryptlib.h"
|
||||
#include <openssl/asn1t.h>
|
||||
|
||||
#if !(OPENSSL_API_COMPAT < 0x10200000L)
|
||||
NON_EMPTY_TRANSLATION_UNIT
|
||||
#else
|
||||
|
||||
#define COPY_SIZE(a, b) (sizeof(a) < sizeof(b) ? sizeof(a) : sizeof(b))
|
||||
|
||||
/*
|
||||
* Custom primitive type for long handling. This converts between an
|
||||
* ASN1_INTEGER and a long directly.
|
||||
*/
|
||||
|
||||
static int long_new(ASN1_VALUE **pval, const ASN1_ITEM *it);
|
||||
static void long_free(ASN1_VALUE **pval, const ASN1_ITEM *it);
|
||||
|
||||
static int long_i2c(ASN1_VALUE **pval, unsigned char *cont, int *putype,
|
||||
const ASN1_ITEM *it);
|
||||
static int long_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len,
|
||||
int utype, char *free_cont, const ASN1_ITEM *it);
|
||||
static int long_print(BIO *out, ASN1_VALUE **pval, const ASN1_ITEM *it,
|
||||
int indent, const ASN1_PCTX *pctx);
|
||||
|
||||
static ASN1_PRIMITIVE_FUNCS long_pf = {
|
||||
NULL, 0,
|
||||
long_new,
|
||||
long_free,
|
||||
long_free, /* Clear should set to initial value */
|
||||
long_c2i,
|
||||
long_i2c,
|
||||
long_print
|
||||
};
|
||||
|
||||
ASN1_ITEM_start(LONG)
|
||||
ASN1_ITYPE_PRIMITIVE, V_ASN1_INTEGER, NULL, 0, &long_pf, ASN1_LONG_UNDEF, "LONG"
|
||||
ASN1_ITEM_end(LONG)
|
||||
|
||||
ASN1_ITEM_start(ZLONG)
|
||||
ASN1_ITYPE_PRIMITIVE, V_ASN1_INTEGER, NULL, 0, &long_pf, 0, "ZLONG"
|
||||
ASN1_ITEM_end(ZLONG)
|
||||
|
||||
static int long_new(ASN1_VALUE **pval, const ASN1_ITEM *it)
|
||||
{
|
||||
memcpy(pval, &it->size, COPY_SIZE(*pval, it->size));
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void long_free(ASN1_VALUE **pval, const ASN1_ITEM *it)
|
||||
{
|
||||
memcpy(pval, &it->size, COPY_SIZE(*pval, it->size));
|
||||
}
|
||||
|
||||
/*
|
||||
* Originally BN_num_bits_word was called to perform this operation, but
|
||||
* trouble is that there is no guarantee that sizeof(long) equals to
|
||||
* sizeof(BN_ULONG). BN_ULONG is a configurable type that can be as wide
|
||||
* as long, but also double or half...
|
||||
*/
|
||||
static int num_bits_ulong(unsigned long value)
|
||||
{
|
||||
size_t i;
|
||||
unsigned long ret = 0;
|
||||
|
||||
/*
|
||||
* It is argued that *on average* constant counter loop performs
|
||||
* not worse [if not better] than one with conditional break or
|
||||
* mask-n-table-lookup-style, because of branch misprediction
|
||||
* penalties.
|
||||
*/
|
||||
for (i = 0; i < sizeof(value) * 8; i++) {
|
||||
ret += (value != 0);
|
||||
value >>= 1;
|
||||
}
|
||||
|
||||
return (int)ret;
|
||||
}
|
||||
|
||||
static int long_i2c(ASN1_VALUE **pval, unsigned char *cont, int *putype,
|
||||
const ASN1_ITEM *it)
|
||||
{
|
||||
long ltmp;
|
||||
unsigned long utmp, sign;
|
||||
int clen, pad, i;
|
||||
|
||||
memcpy(<mp, pval, COPY_SIZE(*pval, ltmp));
|
||||
if (ltmp == it->size)
|
||||
return -1;
|
||||
/*
|
||||
* Convert the long to positive: we subtract one if negative so we can
|
||||
* cleanly handle the padding if only the MSB of the leading octet is
|
||||
* set.
|
||||
*/
|
||||
if (ltmp < 0) {
|
||||
sign = 0xff;
|
||||
utmp = 0 - (unsigned long)ltmp - 1;
|
||||
} else {
|
||||
sign = 0;
|
||||
utmp = ltmp;
|
||||
}
|
||||
clen = num_bits_ulong(utmp);
|
||||
/* If MSB of leading octet set we need to pad */
|
||||
if (!(clen & 0x7))
|
||||
pad = 1;
|
||||
else
|
||||
pad = 0;
|
||||
|
||||
/* Convert number of bits to number of octets */
|
||||
clen = (clen + 7) >> 3;
|
||||
|
||||
if (cont != NULL) {
|
||||
if (pad)
|
||||
*cont++ = (unsigned char)sign;
|
||||
for (i = clen - 1; i >= 0; i--) {
|
||||
cont[i] = (unsigned char)(utmp ^ sign);
|
||||
utmp >>= 8;
|
||||
}
|
||||
}
|
||||
return clen + pad;
|
||||
}
|
||||
|
||||
static int long_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len,
|
||||
int utype, char *free_cont, const ASN1_ITEM *it)
|
||||
{
|
||||
int i;
|
||||
long ltmp;
|
||||
unsigned long utmp = 0, sign = 0x100;
|
||||
|
||||
if (len > 1) {
|
||||
/*
|
||||
* Check possible pad byte. Worst case, we're skipping past actual
|
||||
* content, but since that's only with 0x00 and 0xff and we set neg
|
||||
* accordingly, the result will be correct in the end anyway.
|
||||
*/
|
||||
switch (cont[0]) {
|
||||
case 0xff:
|
||||
cont++;
|
||||
len--;
|
||||
sign = 0xff;
|
||||
break;
|
||||
case 0:
|
||||
cont++;
|
||||
len--;
|
||||
sign = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (len > (int)sizeof(long)) {
|
||||
ASN1err(ASN1_F_LONG_C2I, ASN1_R_INTEGER_TOO_LARGE_FOR_LONG);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (sign == 0x100) {
|
||||
/* Is it negative? */
|
||||
if (len && (cont[0] & 0x80))
|
||||
sign = 0xff;
|
||||
else
|
||||
sign = 0;
|
||||
} else if (((sign ^ cont[0]) & 0x80) == 0) { /* same sign bit? */
|
||||
ASN1err(ASN1_F_LONG_C2I, ASN1_R_ILLEGAL_PADDING);
|
||||
return 0;
|
||||
}
|
||||
utmp = 0;
|
||||
for (i = 0; i < len; i++) {
|
||||
utmp <<= 8;
|
||||
utmp |= cont[i] ^ sign;
|
||||
}
|
||||
ltmp = (long)utmp;
|
||||
if (ltmp < 0) {
|
||||
ASN1err(ASN1_F_LONG_C2I, ASN1_R_INTEGER_TOO_LARGE_FOR_LONG);
|
||||
return 0;
|
||||
}
|
||||
if (sign)
|
||||
ltmp = -ltmp - 1;
|
||||
if (ltmp == it->size) {
|
||||
ASN1err(ASN1_F_LONG_C2I, ASN1_R_INTEGER_TOO_LARGE_FOR_LONG);
|
||||
return 0;
|
||||
}
|
||||
memcpy(pval, <mp, COPY_SIZE(*pval, ltmp));
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int long_print(BIO *out, ASN1_VALUE **pval, const ASN1_ITEM *it,
|
||||
int indent, const ASN1_PCTX *pctx)
|
||||
{
|
||||
long l;
|
||||
|
||||
memcpy(&l, pval, COPY_SIZE(*pval, l));
|
||||
return BIO_printf(out, "%ld\n", l);
|
||||
}
|
||||
#endif
|
||||
47
crypto/asn1/x_pkey.c
Normal file
47
crypto/asn1/x_pkey.c
Normal file
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "internal/cryptlib.h"
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/objects.h>
|
||||
#include <openssl/x509.h>
|
||||
|
||||
X509_PKEY *X509_PKEY_new(void)
|
||||
{
|
||||
X509_PKEY *ret = NULL;
|
||||
|
||||
ret = OPENSSL_zalloc(sizeof(*ret));
|
||||
if (ret == NULL)
|
||||
goto err;
|
||||
|
||||
ret->enc_algor = X509_ALGOR_new();
|
||||
ret->enc_pkey = ASN1_OCTET_STRING_new();
|
||||
if (ret->enc_algor == NULL || ret->enc_pkey == NULL)
|
||||
goto err;
|
||||
|
||||
return ret;
|
||||
err:
|
||||
X509_PKEY_free(ret);
|
||||
ASN1err(ASN1_F_X509_PKEY_NEW, ERR_R_MALLOC_FAILURE);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void X509_PKEY_free(X509_PKEY *x)
|
||||
{
|
||||
if (x == NULL)
|
||||
return;
|
||||
|
||||
X509_ALGOR_free(x->enc_algor);
|
||||
ASN1_OCTET_STRING_free(x->enc_pkey);
|
||||
EVP_PKEY_free(x->dec_pkey);
|
||||
if (x->key_free)
|
||||
OPENSSL_free(x->key_data);
|
||||
OPENSSL_free(x);
|
||||
}
|
||||
39
crypto/asn1/x_sig.c
Normal file
39
crypto/asn1/x_sig.c
Normal file
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "internal/cryptlib.h"
|
||||
#include <openssl/asn1t.h>
|
||||
#include <openssl/x509.h>
|
||||
#include "internal/x509_int.h"
|
||||
|
||||
ASN1_SEQUENCE(X509_SIG) = {
|
||||
ASN1_SIMPLE(X509_SIG, algor, X509_ALGOR),
|
||||
ASN1_SIMPLE(X509_SIG, digest, ASN1_OCTET_STRING)
|
||||
} ASN1_SEQUENCE_END(X509_SIG)
|
||||
|
||||
IMPLEMENT_ASN1_FUNCTIONS(X509_SIG)
|
||||
|
||||
void X509_SIG_get0(const X509_SIG *sig, const X509_ALGOR **palg,
|
||||
const ASN1_OCTET_STRING **pdigest)
|
||||
{
|
||||
if (palg)
|
||||
*palg = sig->algor;
|
||||
if (pdigest)
|
||||
*pdigest = sig->digest;
|
||||
}
|
||||
|
||||
void X509_SIG_getm(X509_SIG *sig, X509_ALGOR **palg,
|
||||
ASN1_OCTET_STRING **pdigest)
|
||||
{
|
||||
if (palg)
|
||||
*palg = sig->algor;
|
||||
if (pdigest)
|
||||
*pdigest = sig->digest;
|
||||
}
|
||||
28
crypto/asn1/x_spki.c
Normal file
28
crypto/asn1/x_spki.c
Normal file
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "internal/cryptlib.h"
|
||||
#include <openssl/x509.h>
|
||||
#include <openssl/asn1t.h>
|
||||
|
||||
ASN1_SEQUENCE(NETSCAPE_SPKAC) = {
|
||||
ASN1_SIMPLE(NETSCAPE_SPKAC, pubkey, X509_PUBKEY),
|
||||
ASN1_SIMPLE(NETSCAPE_SPKAC, challenge, ASN1_IA5STRING)
|
||||
} ASN1_SEQUENCE_END(NETSCAPE_SPKAC)
|
||||
|
||||
IMPLEMENT_ASN1_FUNCTIONS(NETSCAPE_SPKAC)
|
||||
|
||||
ASN1_SEQUENCE(NETSCAPE_SPKI) = {
|
||||
ASN1_SIMPLE(NETSCAPE_SPKI, spkac, NETSCAPE_SPKAC),
|
||||
ASN1_EMBED(NETSCAPE_SPKI, sig_algor, X509_ALGOR),
|
||||
ASN1_SIMPLE(NETSCAPE_SPKI, signature, ASN1_BIT_STRING)
|
||||
} ASN1_SEQUENCE_END(NETSCAPE_SPKI)
|
||||
|
||||
IMPLEMENT_ASN1_FUNCTIONS(NETSCAPE_SPKI)
|
||||
20
crypto/asn1/x_val.c
Normal file
20
crypto/asn1/x_val.c
Normal file
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "internal/cryptlib.h"
|
||||
#include <openssl/asn1t.h>
|
||||
#include <openssl/x509.h>
|
||||
|
||||
ASN1_SEQUENCE(X509_VAL) = {
|
||||
ASN1_SIMPLE(X509_VAL, notBefore, ASN1_TIME),
|
||||
ASN1_SIMPLE(X509_VAL, notAfter, ASN1_TIME)
|
||||
} ASN1_SEQUENCE_END(X509_VAL)
|
||||
|
||||
IMPLEMENT_ASN1_FUNCTIONS(X509_VAL)
|
||||
Reference in New Issue
Block a user