diff options
author | Dr. Stephen Henson <steve@openssl.org> | 1999-10-21 13:20:49 +0000 |
---|---|---|
committer | Dr. Stephen Henson <steve@openssl.org> | 1999-10-21 13:20:49 +0000 |
commit | 462f79ec44fb9259c48be448b231df3073c000d9 (patch) | |
tree | 8d5a7975ef606ac78d2a74fb1944d9bf2a526cd7 /crypto/asn1 | |
parent | 08e9c1af6c26f74ef7f7524be4b89241ff232a8c (diff) |
New function ASN1_mbstring_copy() to handle ASN1 string copying. Ultimately
this will be used to clear up the horrible DN mess.
Diffstat (limited to 'crypto/asn1')
-rw-r--r-- | crypto/asn1/Makefile.ssl | 11 | ||||
-rw-r--r-- | crypto/asn1/a_mbstr.c | 352 | ||||
-rw-r--r-- | crypto/asn1/asn1.h | 14 | ||||
-rw-r--r-- | crypto/asn1/asn1_err.c | 10 |
4 files changed, 383 insertions, 4 deletions
diff --git a/crypto/asn1/Makefile.ssl b/crypto/asn1/Makefile.ssl index 69b98843bf..a1776d5550 100644 --- a/crypto/asn1/Makefile.ssl +++ b/crypto/asn1/Makefile.ssl @@ -24,7 +24,7 @@ APPS= LIB=$(TOP)/libcrypto.a LIBSRC= 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_set.c a_dup.c a_d2i_fp.c a_i2d_fp.c a_bmp.c \ - a_enum.c a_vis.c a_utf8.c a_sign.c a_digest.c a_verify.c \ + a_enum.c a_vis.c a_utf8.c a_sign.c a_digest.c a_verify.c a_mbstr.c \ x_algor.c x_val.c x_pubkey.c x_sig.c x_req.c x_attrib.c \ x_name.c x_cinf.c x_x509.c x_crl.c x_info.c x_spki.c nsseq.c \ d2i_r_pr.c i2d_r_pr.c d2i_r_pu.c i2d_r_pu.c \ @@ -39,7 +39,7 @@ LIBSRC= a_object.c a_bitstr.c a_utctm.c a_gentm.c a_time.c a_int.c a_octet.c \ evp_asn1.c asn_pack.c p5_pbe.c p5_pbev2.c p8_pkey.c LIBOBJ= a_object.o a_bitstr.o a_utctm.o a_gentm.o a_time.o a_int.o a_octet.o \ a_print.o a_type.o a_set.o a_dup.o a_d2i_fp.o a_i2d_fp.o a_bmp.o \ - a_enum.o a_vis.o a_utf8.o a_sign.o a_digest.o a_verify.o \ + a_enum.o a_vis.o a_utf8.o a_sign.o a_digest.o a_verify.o a_mbstr.o \ x_algor.o x_val.o x_pubkey.o x_sig.o x_req.o x_attrib.o \ x_name.o x_cinf.o x_x509.o x_crl.o x_info.o x_spki.o nsseq.o \ d2i_r_pr.o i2d_r_pr.o d2i_r_pu.o i2d_r_pu.o \ @@ -209,6 +209,13 @@ a_int.o: ../../include/openssl/e_os2.h ../../include/openssl/err.h a_int.o: ../../include/openssl/opensslconf.h ../../include/openssl/opensslv.h a_int.o: ../../include/openssl/safestack.h ../../include/openssl/stack.h a_int.o: ../cryptlib.h +a_mbstr.o: ../../include/openssl/asn1.h ../../include/openssl/bio.h +a_mbstr.o: ../../include/openssl/bn.h ../../include/openssl/buffer.h +a_mbstr.o: ../../include/openssl/crypto.h ../../include/openssl/e_os.h +a_mbstr.o: ../../include/openssl/e_os2.h ../../include/openssl/err.h +a_mbstr.o: ../../include/openssl/opensslconf.h ../../include/openssl/opensslv.h +a_mbstr.o: ../../include/openssl/safestack.h ../../include/openssl/stack.h +a_mbstr.o: ../cryptlib.h a_meth.o: ../../include/openssl/asn1.h ../../include/openssl/bio.h a_meth.o: ../../include/openssl/bn.h ../../include/openssl/buffer.h a_meth.o: ../../include/openssl/crypto.h ../../include/openssl/e_os.h diff --git a/crypto/asn1/a_mbstr.c b/crypto/asn1/a_mbstr.c new file mode 100644 index 0000000000..b83e3ee35e --- /dev/null +++ b/crypto/asn1/a_mbstr.c @@ -0,0 +1,352 @@ +/* a_mbstr.c */ +/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL + * project 1999. + */ +/* ==================================================================== + * Copyright (c) 1999 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +#include <stdio.h> +#include "cryptlib.h" +#include <openssl/asn1.h> + +static int traverse_string(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); +static int is_printable(unsigned long value); + +/* This function takes 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 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 :-( + */ + +int ASN1_mbstring_copy(ASN1_STRING **out, unsigned char *in, int len, + int inform, unsigned long mask) +{ + int str_type; + int ret; + int outform, outlen; + ASN1_STRING *dest; + unsigned char *p; + int nchar; + int (*cpyfunc)(unsigned long value, void *in) = NULL; + if(len == -1) len = strlen(in); + + /* 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_COPY, + ASN1_R_INVALID_BMPSTRING_LENGTH); + return -1; + } + nchar = len >> 1; + break; + + case MBSTRING_UNIV: + if(len & 3) { + ASN1err(ASN1_F_ASN1_MBSTRING_COPY, + ASN1_R_INVALID_UNIVERSALSTRING_LENGTH); + return -1; + } + nchar = len >> 2; + break; + + case MBSTRING_UTF8: + nchar = 0; + ret = traverse_string(in, len, MBSTRING_UTF8, in_utf8, &nchar); + if(ret < 0) { + ASN1err(ASN1_F_ASN1_MBSTRING_COPY, + ASN1_R_INVALID_UTF8STRING); + return -1; + } + break; + + case MBSTRING_ASC: + nchar = len; + break; + + default: + ASN1err(ASN1_F_ASN1_MBSTRING_COPY, ASN1_R_UNKNOWN_FORMAT); + return -1; + } + + /* Now work out minimal type (if any) */ + if(traverse_string(in, len, inform, type_str, &mask) < 0) { + ASN1err(ASN1_F_ASN1_MBSTRING_COPY, ASN1_R_ILLEGAL_CHARACTERS); + return -1; + } + + /* Now work out output format and string type */ + outform = MBSTRING_ASC; + 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(!(dest = ASN1_STRING_type_new(str_type))) { + ASN1err(ASN1_F_ASN1_MBSTRING_COPY, 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)) { + ASN1_STRING_free(dest); + ASN1err(ASN1_F_ASN1_MBSTRING_COPY,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 = Malloc(outlen + 1))) { + ASN1_STRING_free(dest); + ASN1err(ASN1_F_ASN1_MBSTRING_COPY,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(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 = *p++ << 24; + value |= *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) +{ + long *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; + types = *((unsigned long *)arg); + if((types & B_ASN1_PRINTABLESTRING) && !is_printable(value)) + types &= ~B_ASN1_PRINTABLESTRING; + if((types & B_ASN1_IA5STRING) && (value > 127)) + 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; +} + +/* Return 1 if the character is permitted in a PrintableString */ +static int is_printable(unsigned long value) +{ + int ch; + if(value > 0x7f) return 0; + ch = (int) value; + /* Note: we can't use 'isalnum' because certain accented + * characters may count as alphanumeric in some environments. + */ + if((ch >= 'a') && (ch <= 'z')) return 1; + if((ch >= 'A') && (ch <= 'Z')) return 1; + if((ch >= '0') && (ch <= '9')) return 1; + if ((ch == ' ') || strchr("'()+,-./:=?", ch)) return 1; + return 0; +} diff --git a/crypto/asn1/asn1.h b/crypto/asn1/asn1.h index edc7aae4b2..832611b713 100644 --- a/crypto/asn1/asn1.h +++ b/crypto/asn1/asn1.h @@ -129,6 +129,12 @@ extern "C" { #define B_ASN1_UNKNOWN 0x1000 #define B_ASN1_UTF8STRING 0x2000 +/* For use with ASN1_mbstring_copy() */ +#define MBSTRING_ASC 1 +#define MBSTRING_BMP 2 +#define MBSTRING_UNIV 3 +#define MBSTRING_UTF8 4 + #define DECLARE_ASN1_SET_OF(type) \ int i2d_ASN1_SET_OF_##type(STACK_OF(type) *a,unsigned char **pp, \ int (*func)(type *,unsigned char **), int ex_tag, \ @@ -712,6 +718,8 @@ unsigned char *ASN1_seq_pack(STACK *safes, int (*i2d)(), unsigned char **buf, int *len ); void *ASN1_unpack_string(ASN1_STRING *oct, char *(*d2i)()); ASN1_STRING *ASN1_pack_string(void *obj, int (*i2d)(), ASN1_OCTET_STRING **oct); +int ASN1_mbstring_copy(ASN1_STRING **out, unsigned char *in, int len, + int inform, unsigned long mask); /* BEGIN ERROR CODES */ /* The following lines are auto generated by the script mkerr.pl. Any changes @@ -738,6 +746,7 @@ ASN1_STRING *ASN1_pack_string(void *obj, int (*i2d)(), ASN1_OCTET_STRING **oct); #define ASN1_F_ASN1_I2D_FP 110 #define ASN1_F_ASN1_INTEGER_SET 111 #define ASN1_F_ASN1_INTEGER_TO_BN 112 +#define ASN1_F_ASN1_MBSTRING_COPY 282 #define ASN1_F_ASN1_OBJECT_NEW 113 #define ASN1_F_ASN1_PACK_STRING 245 #define ASN1_F_ASN1_PBE_SET 253 @@ -933,9 +942,13 @@ ASN1_STRING *ASN1_pack_string(void *obj, int (*i2d)(), ASN1_OCTET_STRING **oct); #define ASN1_R_FIRST_NUM_TOO_LARGE 119 #define ASN1_R_GENERALIZEDTIME_TOO_LONG 153 #define ASN1_R_HEADER_TOO_LONG 120 +#define ASN1_R_ILLEGAL_CHARACTERS 158 +#define ASN1_R_INVALID_BMPSTRING_LENGTH 159 #define ASN1_R_INVALID_DIGIT 121 #define ASN1_R_INVALID_SEPARATOR 122 #define ASN1_R_INVALID_TIME_FORMAT 123 +#define ASN1_R_INVALID_UNIVERSALSTRING_LENGTH 160 +#define ASN1_R_INVALID_UTF8STRING 161 #define ASN1_R_IV_TOO_LARGE 124 #define ASN1_R_LENGTH_ERROR 125 #define ASN1_R_MISSING_SECOND_NUMBER 126 @@ -953,6 +966,7 @@ ASN1_STRING *ASN1_pack_string(void *obj, int (*i2d)(), ASN1_OCTET_STRING **oct); #define ASN1_R_UNABLE_TO_DECODE_RSA_KEY 138 #define ASN1_R_UNABLE_TO_DECODE_RSA_PRIVATE_KEY 139 #define ASN1_R_UNKNOWN_ATTRIBUTE_TYPE 140 +#define ASN1_R_UNKNOWN_FORMAT 162 #define ASN1_R_UNKNOWN_MESSAGE_DIGEST_ALGORITHM 141 #define ASN1_R_UNKNOWN_OBJECT_TYPE 142 #define ASN1_R_UNKNOWN_PUBLIC_KEY_TYPE 143 diff --git a/crypto/asn1/asn1_err.c b/crypto/asn1/asn1_err.c index 16755a0b05..f1a142d375 100644 --- a/crypto/asn1/asn1_err.c +++ b/crypto/asn1/asn1_err.c @@ -75,13 +75,14 @@ static ERR_STRING_DATA ASN1_str_functs[]= {ERR_PACK(0,ASN1_F_ASN1_DUP,0), "ASN1_dup"}, {ERR_PACK(0,ASN1_F_ASN1_ENUMERATED_SET,0), "ASN1_ENUMERATED_set"}, {ERR_PACK(0,ASN1_F_ASN1_ENUMERATED_TO_BN,0), "ASN1_ENUMERATED_to_BN"}, -{ERR_PACK(0,ASN1_F_ASN1_GENERALIZEDTIME_NEW,0), "ASN1_GENERALIZEDTIME_NEW"}, +{ERR_PACK(0,ASN1_F_ASN1_GENERALIZEDTIME_NEW,0), "ASN1_GENERALIZEDTIME_new"}, {ERR_PACK(0,ASN1_F_ASN1_GET_OBJECT,0), "ASN1_get_object"}, {ERR_PACK(0,ASN1_F_ASN1_HEADER_NEW,0), "ASN1_HEADER_new"}, {ERR_PACK(0,ASN1_F_ASN1_I2D_BIO,0), "ASN1_i2d_bio"}, {ERR_PACK(0,ASN1_F_ASN1_I2D_FP,0), "ASN1_i2d_fp"}, {ERR_PACK(0,ASN1_F_ASN1_INTEGER_SET,0), "ASN1_INTEGER_set"}, {ERR_PACK(0,ASN1_F_ASN1_INTEGER_TO_BN,0), "ASN1_INTEGER_to_BN"}, +{ERR_PACK(0,ASN1_F_ASN1_MBSTRING_COPY,0), "ASN1_mbstring_copy"}, {ERR_PACK(0,ASN1_F_ASN1_OBJECT_NEW,0), "ASN1_OBJECT_new"}, {ERR_PACK(0,ASN1_F_ASN1_PACK_STRING,0), "ASN1_pack_string"}, {ERR_PACK(0,ASN1_F_ASN1_PBE_SET,0), "ASN1_PBE_SET"}, @@ -94,7 +95,7 @@ static ERR_STRING_DATA ASN1_str_functs[]= {ERR_PACK(0,ASN1_F_ASN1_TYPE_GET_OCTETSTRING,0), "ASN1_TYPE_get_octetstring"}, {ERR_PACK(0,ASN1_F_ASN1_TYPE_NEW,0), "ASN1_TYPE_new"}, {ERR_PACK(0,ASN1_F_ASN1_UNPACK_STRING,0), "ASN1_unpack_string"}, -{ERR_PACK(0,ASN1_F_ASN1_UTCTIME_NEW,0), "ASN1_UTCTIME_NEW"}, +{ERR_PACK(0,ASN1_F_ASN1_UTCTIME_NEW,0), "ASN1_UTCTIME_new"}, {ERR_PACK(0,ASN1_F_ASN1_VERIFY,0), "ASN1_verify"}, {ERR_PACK(0,ASN1_F_AUTHORITY_KEYID_NEW,0), "AUTHORITY_KEYID_new"}, {ERR_PACK(0,ASN1_F_BASIC_CONSTRAINTS_NEW,0), "BASIC_CONSTRAINTS_new"}, @@ -280,9 +281,13 @@ static ERR_STRING_DATA ASN1_str_reasons[]= {ASN1_R_FIRST_NUM_TOO_LARGE ,"first num too large"}, {ASN1_R_GENERALIZEDTIME_TOO_LONG ,"generalizedtime too long"}, {ASN1_R_HEADER_TOO_LONG ,"header too long"}, +{ASN1_R_ILLEGAL_CHARACTERS ,"illegal characters"}, +{ASN1_R_INVALID_BMPSTRING_LENGTH ,"invalid bmpstring length"}, {ASN1_R_INVALID_DIGIT ,"invalid digit"}, {ASN1_R_INVALID_SEPARATOR ,"invalid separator"}, {ASN1_R_INVALID_TIME_FORMAT ,"invalid time format"}, +{ASN1_R_INVALID_UNIVERSALSTRING_LENGTH ,"invalid universalstring length"}, +{ASN1_R_INVALID_UTF8STRING ,"invalid utf8string"}, {ASN1_R_IV_TOO_LARGE ,"iv too large"}, {ASN1_R_LENGTH_ERROR ,"length error"}, {ASN1_R_MISSING_SECOND_NUMBER ,"missing second number"}, @@ -300,6 +305,7 @@ static ERR_STRING_DATA ASN1_str_reasons[]= {ASN1_R_UNABLE_TO_DECODE_RSA_KEY ,"unable to decode rsa key"}, {ASN1_R_UNABLE_TO_DECODE_RSA_PRIVATE_KEY ,"unable to decode rsa private key"}, {ASN1_R_UNKNOWN_ATTRIBUTE_TYPE ,"unknown attribute type"}, +{ASN1_R_UNKNOWN_FORMAT ,"unknown format"}, {ASN1_R_UNKNOWN_MESSAGE_DIGEST_ALGORITHM ,"unknown message digest algorithm"}, {ASN1_R_UNKNOWN_OBJECT_TYPE ,"unknown object type"}, {ASN1_R_UNKNOWN_PUBLIC_KEY_TYPE ,"unknown public key type"}, |