original files of m241

This commit is contained in:
neelimap
2026-07-30 11:19:44 +05:30
parent 170c2b3f3a
commit afc7070c1f
12254 changed files with 7655111 additions and 0 deletions
@@ -0,0 +1,44 @@
/*
* Copyright (c) 2004, Richard Levitte <richard@levitte.org>
* 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.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifndef LPDIR_H
# include "LPdir.h"
#endif
struct LP_dir_context_st {
void *dummy;
};
const char *LP_find_file(LP_DIR_CTX **ctx, const char *directory)
{
errno = EINVAL;
return 0;
}
int LP_find_file_end(LP_DIR_CTX **ctx)
{
errno = EINVAL;
return 0;
}
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,66 @@
/* crypto/aes/aes_cbc.c */
/* ====================================================================
* Copyright (c) 1998-2002 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
* openssl-core@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.
* ====================================================================
*
*/
#include <sys/types.h>
#include <openssl/aes.h>
#include <openssl/modes.h>
void AES_cbc_encrypt(const unsigned char *in, unsigned char *out,
size_t len, const AES_KEY *key,
unsigned char *ivec, const int enc)
{
if (enc)
CRYPTO_cbc128_encrypt(in, out, len, key, ivec,
(block128_f) AES_encrypt);
else
CRYPTO_cbc128_decrypt(in, out, len, key, ivec,
(block128_f) AES_decrypt);
}
@@ -0,0 +1,519 @@
/*----------------------------------------------------------------------------
// Licensed materials - Property of IBM
//
// (C) Copyright IBM Corp. 2007
// This code was donated to the OpenSSL project under the terms of the
// OpenSSL license.
//
//---------------------------------------------------------------------------*/
/* Note !
AES-CCM is defined as a one-shot encrypt/mac operation
hence there's no AES_CCM_CTX, no Init/Update/Final
It'll also eat a LOT of RAM for long messages.
*/
#ifndef AES_DEBUG
# ifndef NDEBUG
# define NDEBUG
# endif
#endif
#include <assert.h>
#include <sys/types.h>
#include "openssl/evp.h"
#include "openssl/aes.h"
#include "aes_locl.h"
/*
\debug Define: Uncomment to enable debugging of the AES-CCM code
#define AES_CCM_DEBUG 1
*/
#if defined(AES_CCM_DEBUG)
/*! @brief print a tagged binary buffer
@param tag the tag
@param buf the buffer to convert to hex and print
@param blen the length of the buffer
\debug Code: printbin: controlled by AES_CCM_DEBUG
*/
static void printbin(char *tag,unsigned char *buf, int blen)
{
int i;
printf("\t%-12s: ",tag);
for(i = 0; i < blen; i++) {
printf("%02x",(unsigned)buf[i]);
if( (i % 4) == 3) printf(" ");
}
printf("\n");
}
/*! @brief print a tagged binary buffer with an incrementing counter on the tag
@param tag the tag
@param ctr a pointer to the counter
@param buf the buffer to convert to hex and print
@param blen the length of the buffer
\debug Code: printbinCTR: controlled by AES_CCM_DEBUG
*/
static void printbinCTR(char *tag,int *ctr,unsigned char *buf, int blen)
{
char buffer[21];
sprintf(buffer,"%s%1d",tag,*ctr);
(*ctr)++;
printbin(buffer,buf,blen);
}
#else
#define printbin(x,y,z)
#define printbinCTR(x,y,z,q)
#endif
/*! @brief
Increment the CCM CTR, which is variable length, big endian
@param counter the counter to increment
@param q the number of bytes in the counter
*/
static void AES_CCM_inc(unsigned char *counter,unsigned q) {
int i;
for(i = 15; q > 0 ; i--,q--) {
counter[i]++;
if(0 != counter[i] ) break;
}
}
/** @brief xor two buffers into a destination.
(Which may be one of the source buffers )
@param dest the destination buffer
@param s1 first source buffer
@param s2 second source buffer
@param blen buffer length
*/
static void xor(unsigned char *dest, unsigned char *s1, unsigned char *s2, unsigned blen)
{
unsigned int i;
for(i = 0; i < blen; i++) {
dest[i] = s1[i] ^ s2[i];
}
}
/** @brief perform the CCM incremental hash function
@param pcb An ICC library context
@param B The retained hash buffer
@param A the new data to hash in
@param ctx and initialzied Cipher CTX
*/
static void CCM_HASH(unsigned char *B,unsigned char *A,EVP_CIPHER_CTX *ctx)
{
int outl = 0;
/* XOR the encrypted last block (now in B)
with the newly prepared block
*/
xor(A,B,A,AES_BLOCK_SIZE);
/* Encrypt the result, and save it as the "last block" */
/* AES_encrypt(A,B,akey); */
EVP_EncryptUpdate(ctx,B,&outl,A,AES_BLOCK_SIZE);
}
/** @brief Initialize the CCM counter
@param CTR a pointer to the counter buffer
@param iv the nonce
@param ivlen the length of the nonce
@param q the size of the counter fields
*/
static void CCM_FORMAT_CTR(unsigned char *CTR,
unsigned char *iv,
unsigned long ivlen,
unsigned int q)
{
unsigned int i;
/* Format the CTR */
memset(CTR,0,AES_BLOCK_SIZE);
/* Copy in the IV fields */
for(i = 1; i <= ivlen; i ++) {
CTR[i] = iv[i-1];
}
CTR[0] |= ((q-1) & 7);
}
/** @brief
Perform the code common to AES_CCM encrypt and decrypt
provide the iv (Nonce),aad, data and key, output buffer and taglength
@param pcb an ICC library context
@param iv the Nonce, can be 32-128 bits long, < 64 is not recommended
@param ivlen the length of the IV
@param key an aes
@param keylen the length of the AES key in bytes
@param aad Additional Authentication data, hashed, but not encrypted
@param aadlen the length of the aad
@param data the data buffer to encrypt
@param datalen the length of the data buffer
@param out the output buffer
@param outlen a place to store the returned output length
- which WILL be rounded up to a 16 byte boundary +16 bytes
@param taglen the desired length of the auth tag
@param enc 0 = decrypt, else encrypt
@return 1 if O.K., 0 otherwise
*/
static int AES_CCM_Common(unsigned char *iv,unsigned int ivlen,
unsigned char *key,unsigned int keylen,
unsigned char *aad, unsigned long aadlen,
unsigned char *data,unsigned long datalen,
unsigned char *out, unsigned long *outlen,
unsigned int taglen,int enc
)
{
int rv = 1;
EVP_CIPHER_CTX *ctx = NULL;
const EVP_CIPHER *cipher = NULL;
unsigned char A0[AES_BLOCK_SIZE];
unsigned char B0[AES_BLOCK_SIZE];
unsigned char CTR[AES_BLOCK_SIZE];
unsigned char S0[AES_BLOCK_SIZE];
unsigned t = 0;
unsigned q = 0;
unsigned long p = 0;
unsigned char *oldout = out;
unsigned int aadbytes = 0;
unsigned int offset = 0;
int outl = 0;
unsigned int i,j,k;
unsigned int aadenc = 2;
#if defined(AES_CCM_DEBUG)
int b = 0; /* Index counters to aid formatting during debug */
int s = 0;
int c = 0;
#endif
/* Check for a valid aad length */
if(aadlen > 0xFFFFFFFFL) {
rv = 0;
}
/* Check for a valid nonce length 7-13 */
if( (ivlen < 7) || (ivlen > 13) ) {
rv = 0;
} else {
/* Calculate q, the bytes required to hold the possible representation
of the LENGTH of the plaintext from the nonce
*/
q = 15 - ivlen;
}
t = (taglen-2)/2;
/* check for a valid tag length 4,6,8,10,12,14,16 */
if( (0 != (taglen & 1)) || (taglen < 4) || (taglen > 16)) {
rv = 0;
}
if(NULL == outlen) {
rv = 0;
}
switch(keylen) {
case 16:
cipher = EVP_get_cipherbyname("AES-128-ECB");
break;
case 24:
cipher = EVP_get_cipherbyname("AES-192-ECB");
break;
case 32:
cipher = EVP_get_cipherbyname("AES-256-ECB");
break;
default:
rv = 0;
break;
}
ctx = EVP_CIPHER_CTX_new();
if( 1 == rv ) {
*outlen = 0; /* Clear the output data length */
/* Now - to prevent the user from knowing why we failed
always flush the output buffers
*/
if(enc) {
/* In encrypt mode, clear the output buffer */
memset(out,0,(((datalen+15)/16)*16)+taglen);
} else {
/* Same in decrypt mode */
memset(out,0,datalen-taglen);
}
EVP_CIPHER_CTX_set_padding(ctx,0);
EVP_EncryptInit(ctx,cipher,key,NULL);
}
if (1 == rv ) {
/* If we are decrypting, we don't decrypt the tag ... */
if( ! enc ) {
datalen -= taglen;
}
/* Format the first block */
memset(B0,0,AES_BLOCK_SIZE);
/* Do we have adata ? */
if(aad != NULL && aadlen > 0) {
B0[0] |= 0x40;
}
B0[0] |= (((taglen-2)/2) & 7) << 3;
B0[0] |= (q - 1) & 7;
/* Copy in the IV fields */
for(i = 1; i <= ivlen; i ++) {
B0[i] = iv[i-1];
}
/*
Encode the number of bytes of plaintext
in the remaining space
*/
p = datalen;;
for( j = 15 ; j > i ; j--) {
B0[j] = (p & 0xff);
p >>= 8;
}
printbinCTR("B",&b,B0,16);
memset(A0,0,AES_BLOCK_SIZE); /* Start with original data == 0 */
CCM_HASH(B0,A0,ctx);
CCM_FORMAT_CTR(CTR,iv,ivlen,q);
/*
now any aadata
*/
memset(A0,0,AES_BLOCK_SIZE);
if(aad != NULL && aadlen > 0) {
if(aadlen < (0x10000L - 0x100L)) {
aadbytes = 2;
aadenc = 2;
} else if(aadlen <= 0xFFFFFFFF) {
aadbytes = 6;
aadenc = 4;
A0[0] = 0xff;
A0[1] = 0xfe;
} else {
aadbytes = 10;
aadenc = 8;
A0[0] = 0xff;
A0[1] = 0xff;
}
j = aadlen;
for(i = 0, k = aadbytes-1; i < aadenc; i++,k--) {
A0[k] = j & 0xff;
j = j / 256;
}
/* Now roll through the aad ? */
}
/* Free space in A0.16 - (1 byte flags + aadbytes) */
offset = aadbytes;
j = 16 - offset;
/* j is the number of bytes to copy,
offset is the offset into the buffer to start
the copy
*/
for( ;aadlen > 0 ; aadlen -= j,j = AES_BLOCK_SIZE) {
/* If the remaining free space is less than the aadlength
copy only the aadlength
*/
if( j > aadlen) {
j = aadlen;
}
/* start at buffer + flags + stored length
copy the requistite ammount of aad
*/
memcpy(A0+offset,aad,j);
if(offset+j < 16) {
memset(A0+offset+j,0,(16-(offset+j)));
}
printbinCTR("B",&b,A0,16);
CCM_HASH(B0,A0,ctx);
aad += j;
/* Now encrypt the result, and store it in B0 */
offset = 0; /* offset can only be zero the first time through */
if(aadlen <= j) break; /* aadlen is unsigned, this ensures we exit */
}
/* Process the first counter block */
printbinCTR("CTR",&c,CTR,AES_BLOCK_SIZE);
/* AES_encrypt(CTR,A0,akey); */
EVP_EncryptUpdate(ctx,A0,&outl,CTR,AES_BLOCK_SIZE);
printbinCTR("S",&s,A0,AES_BLOCK_SIZE);
AES_CCM_inc(CTR,q);
memcpy(S0,A0,AES_BLOCK_SIZE);
/* Now do the encrypt/decrypt phase, note that we are still adding data to the
hash function at this phase as well.
*/
for( ; datalen > 0; datalen -= AES_BLOCK_SIZE) {
int l = AES_BLOCK_SIZE;
if(datalen < AES_BLOCK_SIZE) {
l = datalen;
/* In this case we need to zero A0 */
memset(A0,0,AES_BLOCK_SIZE);
}
if(enc) {
memcpy(A0,data,l);
printbinCTR("B",&b,A0,AES_BLOCK_SIZE);
CCM_HASH(B0,A0,ctx);
}
/* Prep the counter - encrypt the current value
*/
printbinCTR("CTR",&c,CTR,AES_BLOCK_SIZE);
/* AES_encrypt(CTR,A0,akey); */
EVP_EncryptUpdate(ctx,A0,&outl,CTR,AES_BLOCK_SIZE);
printbinCTR("S",&s,A0,AES_BLOCK_SIZE);
/* Increment the counter */
AES_CCM_inc(CTR,q);
/* XOR the encrypted counter with the incoming data */
xor(A0,data,A0,l);
/* Copy this to the output */
memcpy(out,A0,l);
printbin("C",A0,l);
/* In decrypt mode, that gave us plaintext which
we hash
*/
if( !enc ) {
if(l != AES_BLOCK_SIZE) {
memset(A0+l,0,AES_BLOCK_SIZE-l);
}
printbinCTR("B",&b,A0,AES_BLOCK_SIZE);
CCM_HASH(B0,A0,ctx);
}
data += l;
out += l;
*outlen += l;
if(datalen < AES_BLOCK_SIZE) {
break;
}
}
}
if(1 == rv ) {
/* last encrypted hash block is our tag */
printbin("T",B0,taglen);
/* XOR this with the saved first counter block */
xor(B0,S0,B0,taglen);
/* append this to the encrypted data in encrypt mode */
if( enc ) {
memcpy(out,B0,taglen);
*outlen += taglen;
} else {
/* If it's decrypt mode, we compare it with the end of the data */
if(memcmp(B0,data,taglen) != 0 ) {
rv = 0;
memset(oldout,0,*outlen);
}
}
}
if(NULL != ctx) {
EVP_CIPHER_CTX_cleanup(ctx);
EVP_CIPHER_CTX_free(ctx);
}
return rv;
}
/** @brief
Perform an AES CCM Encrypt operation,
provide the iv (Nonce),aad, data and key, output buffer and taglength
@param pcb an ICC library context
@param iv The Nonce, can be 32-128 bits long, < 64 is not recommended
@param ivlen the length of the IV
@param key an aes key
@param keylen the length of the AES key in bytes
@param aad Additional Authentication data, hashed, but not encrypted
@param aadlen the length of the aad
@param data the data buffer to encrypt
@param datalen the length of the data buffer
@param out the output buffer
@param outlen a place to store the returned output length
- which WILL be rounded up to a 16 byte boundary +16 bytes
@param taglen the desired length of the auth tag
@return 1 if O.K., 0 otherwise
*/
int AES_CCM_Encrypt(unsigned char *iv,unsigned int ivlen,
unsigned char *key,unsigned int keylen,
unsigned char *aad, unsigned long aadlen,
unsigned char *data,unsigned long datalen,
unsigned char *out, unsigned long *outlen,
unsigned int taglen
)
{
int rv = 1;
rv = AES_CCM_Common(iv,ivlen,
key,keylen,
aad,aadlen,
data,datalen,
out,outlen,
taglen,1);
return rv;
}
/** @brief
Perform an AES CCM Decrypt operation,
provide the iv (Nonce),aad, data and key, output buffer and taglength
@param pcb an ICC library context
@param iv The Nonce, can be 32-128 bits long, < 64 is not recommended
@param ivlen the length of the IV
@param key an aes key
@param keylen the length of the AES key
@param aad Additional Authentication data, hashed, but not encrypted
@param aadlen the length of the aad
@param data the data buffer to encrypt
@param datalen the length of the data buffer
@param out the output buffer
@param outlen a place to store the returned output length
@param taglen the length of the auth tag
@return 1 if O.K., 0 otherwise
@note This (by spec) returns no data on failure. However as
we'd have to allocate an internal buffer, which would still be
accessable to the caller within the same process, we simple
erase any partial data in the output buffer on failure instead.
- So , be aware that the output buffer WILL be overwritten,
no matter what.
@note the fact that this isn't allowed to return any data if the
tag match fails is the reason why there can't be the usual
Init/Update/Update/Final API.
*/
int AES_CCM_Decrypt(unsigned char *iv,unsigned int ivlen,
unsigned char *key,unsigned int keylen,
unsigned char *aad, unsigned long aadlen,
unsigned char *data,unsigned long datalen,
unsigned char *out, unsigned long *outlen,
unsigned int taglen
)
{
int rv = 1;
rv = AES_CCM_Common(iv,ivlen,
key,keylen,
aad,aadlen,
data,datalen,
out,outlen,
taglen,0);
if(0 == rv) { /* If anything failed, kill the output buffer */
memset(out,0,*outlen);
*outlen = 0;
}
return rv;
}
@@ -0,0 +1,449 @@
/*----------------------------------------------------------------------------
// Licensed materials - Property of IBM
//
// (C) Copyright IBM Corp. 2007
// This code was donated to the OpenSSL project under the terms of the
// OpenSSL license.
//
//--------------------------------------------------------------------------*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "openssl/err.h"
#include "openssl/evp.h"
#include "openssl/aes_ccm.h"
#include "hex_utils.h"
/* This is ugly, I blame the build system */
#include "hex_utils.c"
static int verbose = 0;
/*
Pull in the API opaque AES_GCM struct as we need to have access
to that for validating the test results
*/
#include "openssl/aes.h"
int aes_ccm_test_main(int argc,char *argv[]);
typedef struct struct_Ci {
char *C;
char *S;
} Ci;
typedef struct struct_CCM_T {
char *K;
char *N;
char *A;
char *P;
char *B;
char *T;
Ci Ci[3];
char *C;
} CCM_T;
CCM_T ccm_data[3] = {
{
"404142434445464748494a4b4c4d4e4f",
"10111213141516",
"0001020304050607",
"20212223",
"4f1011121314151600000000000000040008000102030405060700000000000020212223000000000000000000000000",
"6084341b",
{
{
"07101112131415160000000000000000",
"2d28114610676c2632bad748559a679a"
},
{
"07101112131415160000000000000001",
"51432378e474b33971318484103cddfb"
},
{
NULL,
NULL
},
},
"7162015b4dac255d"
},
{
/* End of first block */
"404142434445464748494a4b4c4d4e4f",
"1011121314151617",
"000102030405060708090a0b0c0d0e0f",
"202122232425262728292a2b2c2d2e2f",
"561011121314151617000000000000100010000102030405060708090a0b0c0d0e0f0000000000000000000000000000202122232425262728292a2b2c2d2e2f",
"7f479ffca464",
{
{
"06101112131415161700000000000000",
"6081d04308a97dcc20cdcc60bf947b78"
},
{
"06101112131415161700000000000001",
"f280d2c375cf794520335db92b107712"
},
{
NULL,
NULL,
},
},
"d2a1f0e051ea5f62081a7792073d593d1fc64fbfaccd"
},
{
/* Third set */
"404142434445464748494a4b4c4d4e4f",
"101112131415161718191a1b",
"000102030405060708090a0b0c0d0e0f10111213",
"202122232425262728292a2b2c2d2e2f3031323334353637",
"5a101112131415161718191a1b0000180014000102030405060708090a0b0c0d0e0f1011121300000000000000000000202122232425262728292a2b2c2d2e2f30313233343536370000000000000000",
"67c99240c7d51048",
{
{
"02101112131415161718191a1b000000",
"2f8a00bb06658919c3a040a6eaed1a7f"
},
{
"02101112131415161718191a1b000001",
"c393238ad1923c5db335c0c7e1bac924"
},
{
"02101112131415161718191a1b000002",
"514798ea9077bc926c22ebef2ac732dc"
},
},
"e3b201a9f5b71a7a9b1ceaeccd97e70b"
}
};
static void pbin(char *tag,unsigned char *buf, int blen)
{
int i;
if(verbose) {
printf("%-20s: ",tag);
for(i = 0; i < blen; i++) {
printf("%02x",(unsigned)buf[i]);
if( (i % 16) == 15) printf("\n%-20s: ","");
else if( (i % 4) == 3) printf(" ");
}
printf("\n");
}
}
/* Compare a binary buffer with it's expected value in hex
the size of the binary buffer is calculated from the hex "known answer"
*/
static int cmp(char *tag,char *ref,unsigned char *bin)
{
int rv = 0;
char *tmp = NULL;
Bin2HexBuffer((char *)bin,strlen(ref)/2,&tmp);
rv = strcmp(ref,tmp);
if(0 != rv) {
if(verbose) {
printf("%-10s = %s\ngot %s\n",tag,ref,tmp);
}
}
free(tmp);
return rv;
}
static void freeme(unsigned char **ptr)
{
if(*ptr) {
free(*ptr);
*ptr = NULL;
}
}
int aes_ccm_test_main(int argc,char *argv[])
{
int rv = 0,fail = 0;
unsigned char *key = NULL;
unsigned long ctlen = 0;
unsigned char *ciphertext = NULL;
unsigned long ptlen = 0;
unsigned char *plaintext = NULL;
unsigned long nlen = 0;
unsigned char *nonce = NULL;
unsigned long aadlen = 0;
unsigned char *aad = NULL;
unsigned int taglen = 0;
unsigned long outlen = 0;
unsigned char *out = NULL;
int result = 0;
int i;
OPENSSL_add_all_algorithms_noconf();
if(verbose) {
printf("Starting AES_CCM Unit Test...\n");
}
if((argc > 1) && (strncmp("-v",argv[1],2) == 0) ) {
verbose = 1;
}
for(i = 0; i < 3; i++) {
/* key */
Hex2BinBuffer(ccm_data[i].K,32,(char **)&key);
pbin("K",key,16);
/* nonce */
nlen = strlen(ccm_data[i].N)/2;
Hex2BinBuffer(ccm_data[i].N,nlen * 2,(char **)&nonce);
pbin("N",nonce,nlen);
/* AAD */
aadlen = strlen(ccm_data[i].A)/2;
Hex2BinBuffer(ccm_data[i].A,aadlen * 2,(char **)&aad);
pbin("A",aad,aadlen);
/* plaintext */
ptlen = strlen(ccm_data[i].P)/2;
Hex2BinBuffer(ccm_data[i].P,ptlen * 2,(char **)&plaintext);
pbin("P",plaintext,ptlen);
out = malloc(ptlen + 64);
taglen = strlen(ccm_data[i].T)/2;
AES_CCM_Encrypt(nonce,nlen,
key,16,
aad,aadlen,
plaintext,ptlen,
out, &outlen,
taglen);
if( cmp("Ciphertext",ccm_data[i].C,out) ) {
rv = 0;
}
pbin("C",out,outlen);
ciphertext = malloc(outlen);
memcpy(ciphertext,out,outlen);
ctlen = outlen;
memset(out,0,outlen);
result = AES_CCM_Decrypt(nonce,nlen,
key,16,
aad,aadlen,
ciphertext,ctlen,
out,&outlen,
taglen);
if( cmp("Plaintext",ccm_data[i].P,out) ) {
rv = 0;
}
if(verbose) {
printf("Should pass test %d: Result = %d, outlen = %ld\n",i,result,outlen);
}
if(result == 0) {
fail++;
}
freeme(&out);
freeme(&key);
freeme(&nonce);
freeme(&aad);
freeme(&plaintext);
freeme(&ciphertext);
}
/* Mess with the nonce on decrypt .. */
for(i = 0; i < 3; i++) {
/* key */
Hex2BinBuffer(ccm_data[i].K,32,(char **)&key);
pbin("K",key,16);
/* nonce */
nlen = strlen(ccm_data[i].N)/2;
Hex2BinBuffer(ccm_data[i].N,nlen * 2,(char **)&nonce);
pbin("N",nonce,nlen);
/* AAD */
aadlen = strlen(ccm_data[i].A)/2;
Hex2BinBuffer(ccm_data[i].A,aadlen * 2,(char **)&aad);
pbin("A",aad,aadlen);
/* plaintext */
ptlen = strlen(ccm_data[i].P)/2;
Hex2BinBuffer(ccm_data[i].P,ptlen * 2,(char **)&plaintext);
pbin("P",plaintext,ptlen);
out = malloc(ptlen + 64);
taglen = strlen(ccm_data[i].T)/2;
AES_CCM_Encrypt(nonce,nlen,
key,16,
aad,aadlen,
plaintext,ptlen,
out, &outlen,
taglen);
if( cmp("Ciphertext",ccm_data[i].C,out) ) {
rv = 0;
}
pbin("C",out,outlen);
ciphertext = malloc(outlen);
memcpy(ciphertext,out,outlen);
ctlen = outlen;
memset(out,0,outlen);
*nonce = ~(*nonce);
result = AES_CCM_Decrypt(nonce,nlen,
key,16,
aad,aadlen,
ciphertext,ctlen,
out,&outlen,
taglen);
if(verbose) {
printf("Should Fail Nonce test %d: Result = %d, outlen = %ld\n",i,result,outlen);
}
if(result == 1) {
fail ++;
}
freeme(&out);
freeme(&key);
freeme(&nonce);
freeme(&aad);
freeme(&plaintext);
freeme(&ciphertext);
}
/* Mess with the aad on decrypt .. */
for(i = 0; i < 3; i++) {
/* key */
Hex2BinBuffer(ccm_data[i].K,32,(char **)&key);
pbin("K",key,16);
/* nonce */
nlen = strlen(ccm_data[i].N)/2;
Hex2BinBuffer(ccm_data[i].N,nlen * 2,(char **)&nonce);
pbin("N",nonce,nlen);
/* AAD */
aadlen = strlen(ccm_data[i].A)/2;
Hex2BinBuffer(ccm_data[i].A,aadlen * 2,(char **)&aad);
pbin("A",aad,aadlen);
/* plaintext */
ptlen = strlen(ccm_data[i].P)/2;
Hex2BinBuffer(ccm_data[i].P,ptlen * 2,(char **)&plaintext);
pbin("P",plaintext,ptlen);
out = malloc(ptlen + 64);
taglen = strlen(ccm_data[i].T)/2;
AES_CCM_Encrypt(nonce,nlen,
key,16,
aad,aadlen,
plaintext,ptlen,
out, &outlen,
taglen);
if( cmp("Ciphertext",ccm_data[i].C,out) ) {
rv = 0;
}
pbin("C",out,outlen);
ciphertext = malloc(outlen);
memcpy(ciphertext,out,outlen);
ctlen = outlen;
memset(out,0,outlen);
*aad = ~(*aad);
result = AES_CCM_Decrypt(nonce,nlen,
key,16,
aad,aadlen,
ciphertext,ctlen,
out,&outlen,
taglen);
if(verbose) {
printf("Should Fail test damaged AAD %d: Result = %d, outlen = %ld\n",i,result,outlen);
}
if(result == 1) {
fail ++;
}
freeme(&out);
freeme(&key);
freeme(&nonce);
freeme(&aad);
freeme(&plaintext);
freeme(&ciphertext);
}
/* Mess with the data on decrypt .. */
for(i = 0; i < 3; i++) {
/* key */
Hex2BinBuffer(ccm_data[i].K,32,(char **)&key);
pbin("K",key,16);
/* nonce */
nlen = strlen(ccm_data[i].N)/2;
Hex2BinBuffer(ccm_data[i].N,nlen * 2,(char **)&nonce);
pbin("N",nonce,nlen);
/* AAD */
aadlen = strlen(ccm_data[i].A)/2;
Hex2BinBuffer(ccm_data[i].A,aadlen * 2,(char **)&aad);
pbin("A",aad,aadlen);
/* plaintext */
ptlen = strlen(ccm_data[i].P)/2;
Hex2BinBuffer(ccm_data[i].P,ptlen * 2,(char **)&plaintext);
pbin("P",plaintext,ptlen);
out = malloc(ptlen + 64);
taglen = strlen(ccm_data[i].T)/2;
AES_CCM_Encrypt(nonce,nlen,
key,16,
aad,aadlen,
plaintext,ptlen,
out, &outlen,
taglen);
if( cmp("Ciphertext",ccm_data[i].C,out) ) {
rv = 0;
}
pbin("C",out,outlen);
ciphertext = malloc(outlen);
memcpy(ciphertext,out,outlen);
ctlen = outlen;
memset(out,0,outlen);
*ciphertext = ~(*ciphertext);
result = AES_CCM_Decrypt(nonce,nlen,
key,16,
aad,aadlen,
ciphertext,ctlen,
out,&outlen,
taglen);
if(verbose) {
printf("Should Fail test damaged ciphertext %d: Result = %d, outlen = %ld\n",i,result,outlen);
}
if(result == 1) {
fail ++;
}
freeme(&out);
freeme(&key);
freeme(&nonce);
freeme(&aad);
freeme(&plaintext);
freeme(&ciphertext);
}
if(!fail && verbose && 0 == rv ) {
printf("AES_CCM Unit Test Successfully Completed!\n");
}
if(fail) {
printf("AES CCM test, %d failures !\n",fail);
rv = 1;
}
EVP_cleanup();
CRYPTO_cleanup_all_ex_data();
ERR_remove_state(0);
ERR_free_strings();
CRYPTO_mem_leaks_fp(stderr);
return rv;
}
@@ -0,0 +1,86 @@
/* crypto/aes/aes_cfb.c */
/* ====================================================================
* Copyright (c) 2002-2006 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
* openssl-core@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.
* ====================================================================
*
*/
#include <sys/types.h>
#include <openssl/aes.h>
#include <openssl/modes.h>
/*
* The input and output encrypted as though 128bit cfb mode is being used.
* The extra state information to record how much of the 128bit block we have
* used is contained in *num;
*/
void AES_cfb128_encrypt(const unsigned char *in, unsigned char *out,
size_t length, const AES_KEY *key,
unsigned char *ivec, int *num, const int enc)
{
CRYPTO_cfb128_encrypt(in, out, length, key, ivec, num, enc,
(block128_f) AES_encrypt);
}
/* N.B. This expects the input to be packed, MS bit first */
void AES_cfb1_encrypt(const unsigned char *in, unsigned char *out,
size_t length, const AES_KEY *key,
unsigned char *ivec, int *num, const int enc)
{
CRYPTO_cfb128_1_encrypt(in, out, length, key, ivec, num, enc,
(block128_f) AES_encrypt);
}
void AES_cfb8_encrypt(const unsigned char *in, unsigned char *out,
size_t length, const AES_KEY *key,
unsigned char *ivec, int *num, const int enc)
{
CRYPTO_cfb128_8_encrypt(in, out, length, key, ivec, num, enc,
(block128_f) AES_encrypt);
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,64 @@
/* crypto/aes/aes_ctr.c */
/* ====================================================================
* Copyright (c) 1998-2002 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
* openssl-core@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.
* ====================================================================
*
*/
#include <sys/types.h>
#include <openssl/aes.h>
#include <openssl/modes.h>
void AES_ctr128_encrypt(const unsigned char *in, unsigned char *out,
size_t length, const AES_KEY *key,
unsigned char ivec[AES_BLOCK_SIZE],
unsigned char ecount_buf[AES_BLOCK_SIZE],
unsigned int *num)
{
CRYPTO_ctr128_encrypt(in, out, length, key, ivec, ecount_buf, num,
(block128_f) AES_encrypt);
}
@@ -0,0 +1,73 @@
/* crypto/aes/aes_ecb.c */
/* ====================================================================
* Copyright (c) 1998-2002 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
* openssl-core@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.
* ====================================================================
*
*/
#ifndef AES_DEBUG
# ifndef NDEBUG
# define NDEBUG
# endif
#endif
#include <assert.h>
#include <openssl/aes.h>
#include "aes_locl.h"
void AES_ecb_encrypt(const unsigned char *in, unsigned char *out,
const AES_KEY *key, const int enc)
{
assert(in && out && key);
assert((AES_ENCRYPT == enc) || (AES_DECRYPT == enc));
if (AES_ENCRYPT == enc)
AES_encrypt(in, out, key);
else
AES_decrypt(in, out, key);
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,323 @@
/* crypto/aes/aes_ige.c */
/* ====================================================================
* Copyright (c) 2006 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
* openssl-core@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.
* ====================================================================
*
*/
#include "cryptlib.h"
#include <openssl/aes.h>
#include "aes_locl.h"
#define N_WORDS (AES_BLOCK_SIZE / sizeof(unsigned long))
typedef struct {
unsigned long data[N_WORDS];
} aes_block_t;
/* XXX: probably some better way to do this */
#if defined(__i386__) || defined(__x86_64__)
# define UNALIGNED_MEMOPS_ARE_FAST 1
#else
# define UNALIGNED_MEMOPS_ARE_FAST 0
#endif
#if UNALIGNED_MEMOPS_ARE_FAST
# define load_block(d, s) (d) = *(const aes_block_t *)(s)
# define store_block(d, s) *(aes_block_t *)(d) = (s)
#else
# define load_block(d, s) memcpy((d).data, (s), AES_BLOCK_SIZE)
# define store_block(d, s) memcpy((d), (s).data, AES_BLOCK_SIZE)
#endif
/* N.B. The IV for this mode is _twice_ the block size */
void AES_ige_encrypt(const unsigned char *in, unsigned char *out,
size_t length, const AES_KEY *key,
unsigned char *ivec, const int enc)
{
size_t n;
size_t len = length;
OPENSSL_assert(in && out && key && ivec);
OPENSSL_assert((AES_ENCRYPT == enc) || (AES_DECRYPT == enc));
OPENSSL_assert((length % AES_BLOCK_SIZE) == 0);
len = length / AES_BLOCK_SIZE;
if (AES_ENCRYPT == enc) {
if (in != out &&
(UNALIGNED_MEMOPS_ARE_FAST
|| ((size_t)in | (size_t)out | (size_t)ivec) % sizeof(long) ==
0)) {
aes_block_t *ivp = (aes_block_t *) ivec;
aes_block_t *iv2p = (aes_block_t *) (ivec + AES_BLOCK_SIZE);
while (len) {
aes_block_t *inp = (aes_block_t *) in;
aes_block_t *outp = (aes_block_t *) out;
for (n = 0; n < N_WORDS; ++n)
outp->data[n] = inp->data[n] ^ ivp->data[n];
AES_encrypt((unsigned char *)outp->data,
(unsigned char *)outp->data, key);
for (n = 0; n < N_WORDS; ++n)
outp->data[n] ^= iv2p->data[n];
ivp = outp;
iv2p = inp;
--len;
in += AES_BLOCK_SIZE;
out += AES_BLOCK_SIZE;
}
memcpy(ivec, ivp->data, AES_BLOCK_SIZE);
memcpy(ivec + AES_BLOCK_SIZE, iv2p->data, AES_BLOCK_SIZE);
} else {
aes_block_t tmp, tmp2;
aes_block_t iv;
aes_block_t iv2;
load_block(iv, ivec);
load_block(iv2, ivec + AES_BLOCK_SIZE);
while (len) {
load_block(tmp, in);
for (n = 0; n < N_WORDS; ++n)
tmp2.data[n] = tmp.data[n] ^ iv.data[n];
AES_encrypt((unsigned char *)tmp2.data,
(unsigned char *)tmp2.data, key);
for (n = 0; n < N_WORDS; ++n)
tmp2.data[n] ^= iv2.data[n];
store_block(out, tmp2);
iv = tmp2;
iv2 = tmp;
--len;
in += AES_BLOCK_SIZE;
out += AES_BLOCK_SIZE;
}
memcpy(ivec, iv.data, AES_BLOCK_SIZE);
memcpy(ivec + AES_BLOCK_SIZE, iv2.data, AES_BLOCK_SIZE);
}
} else {
if (in != out &&
(UNALIGNED_MEMOPS_ARE_FAST
|| ((size_t)in | (size_t)out | (size_t)ivec) % sizeof(long) ==
0)) {
aes_block_t *ivp = (aes_block_t *) ivec;
aes_block_t *iv2p = (aes_block_t *) (ivec + AES_BLOCK_SIZE);
while (len) {
aes_block_t tmp;
aes_block_t *inp = (aes_block_t *) in;
aes_block_t *outp = (aes_block_t *) out;
for (n = 0; n < N_WORDS; ++n)
tmp.data[n] = inp->data[n] ^ iv2p->data[n];
AES_decrypt((unsigned char *)tmp.data,
(unsigned char *)outp->data, key);
for (n = 0; n < N_WORDS; ++n)
outp->data[n] ^= ivp->data[n];
ivp = inp;
iv2p = outp;
--len;
in += AES_BLOCK_SIZE;
out += AES_BLOCK_SIZE;
}
memcpy(ivec, ivp->data, AES_BLOCK_SIZE);
memcpy(ivec + AES_BLOCK_SIZE, iv2p->data, AES_BLOCK_SIZE);
} else {
aes_block_t tmp, tmp2;
aes_block_t iv;
aes_block_t iv2;
load_block(iv, ivec);
load_block(iv2, ivec + AES_BLOCK_SIZE);
while (len) {
load_block(tmp, in);
tmp2 = tmp;
for (n = 0; n < N_WORDS; ++n)
tmp.data[n] ^= iv2.data[n];
AES_decrypt((unsigned char *)tmp.data,
(unsigned char *)tmp.data, key);
for (n = 0; n < N_WORDS; ++n)
tmp.data[n] ^= iv.data[n];
store_block(out, tmp);
iv = tmp2;
iv2 = tmp;
--len;
in += AES_BLOCK_SIZE;
out += AES_BLOCK_SIZE;
}
memcpy(ivec, iv.data, AES_BLOCK_SIZE);
memcpy(ivec + AES_BLOCK_SIZE, iv2.data, AES_BLOCK_SIZE);
}
}
}
/*
* Note that its effectively impossible to do biIGE in anything other
* than a single pass, so no provision is made for chaining.
*/
/* N.B. The IV for this mode is _four times_ the block size */
void AES_bi_ige_encrypt(const unsigned char *in, unsigned char *out,
size_t length, const AES_KEY *key,
const AES_KEY *key2, const unsigned char *ivec,
const int enc)
{
size_t n;
size_t len = length;
unsigned char tmp[AES_BLOCK_SIZE];
unsigned char tmp2[AES_BLOCK_SIZE];
unsigned char tmp3[AES_BLOCK_SIZE];
unsigned char prev[AES_BLOCK_SIZE];
const unsigned char *iv;
const unsigned char *iv2;
OPENSSL_assert(in && out && key && ivec);
OPENSSL_assert((AES_ENCRYPT == enc) || (AES_DECRYPT == enc));
OPENSSL_assert((length % AES_BLOCK_SIZE) == 0);
if (AES_ENCRYPT == enc) {
/*
* XXX: Do a separate case for when in != out (strictly should check
* for overlap, too)
*/
/* First the forward pass */
iv = ivec;
iv2 = ivec + AES_BLOCK_SIZE;
while (len >= AES_BLOCK_SIZE) {
for (n = 0; n < AES_BLOCK_SIZE; ++n)
out[n] = in[n] ^ iv[n];
AES_encrypt(out, out, key);
for (n = 0; n < AES_BLOCK_SIZE; ++n)
out[n] ^= iv2[n];
iv = out;
memcpy(prev, in, AES_BLOCK_SIZE);
iv2 = prev;
len -= AES_BLOCK_SIZE;
in += AES_BLOCK_SIZE;
out += AES_BLOCK_SIZE;
}
/* And now backwards */
iv = ivec + AES_BLOCK_SIZE * 2;
iv2 = ivec + AES_BLOCK_SIZE * 3;
len = length;
while (len >= AES_BLOCK_SIZE) {
out -= AES_BLOCK_SIZE;
/*
* XXX: reduce copies by alternating between buffers
*/
memcpy(tmp, out, AES_BLOCK_SIZE);
for (n = 0; n < AES_BLOCK_SIZE; ++n)
out[n] ^= iv[n];
/*
* hexdump(stdout, "out ^ iv", out, AES_BLOCK_SIZE);
*/
AES_encrypt(out, out, key);
/*
* hexdump(stdout,"enc", out, AES_BLOCK_SIZE);
*/
/*
* hexdump(stdout,"iv2", iv2, AES_BLOCK_SIZE);
*/
for (n = 0; n < AES_BLOCK_SIZE; ++n)
out[n] ^= iv2[n];
/*
* hexdump(stdout,"out", out, AES_BLOCK_SIZE);
*/
iv = out;
memcpy(prev, tmp, AES_BLOCK_SIZE);
iv2 = prev;
len -= AES_BLOCK_SIZE;
}
} else {
/* First backwards */
iv = ivec + AES_BLOCK_SIZE * 2;
iv2 = ivec + AES_BLOCK_SIZE * 3;
in += length;
out += length;
while (len >= AES_BLOCK_SIZE) {
in -= AES_BLOCK_SIZE;
out -= AES_BLOCK_SIZE;
memcpy(tmp, in, AES_BLOCK_SIZE);
memcpy(tmp2, in, AES_BLOCK_SIZE);
for (n = 0; n < AES_BLOCK_SIZE; ++n)
tmp[n] ^= iv2[n];
AES_decrypt(tmp, out, key);
for (n = 0; n < AES_BLOCK_SIZE; ++n)
out[n] ^= iv[n];
memcpy(tmp3, tmp2, AES_BLOCK_SIZE);
iv = tmp3;
iv2 = out;
len -= AES_BLOCK_SIZE;
}
/* And now forwards */
iv = ivec;
iv2 = ivec + AES_BLOCK_SIZE;
len = length;
while (len >= AES_BLOCK_SIZE) {
memcpy(tmp, out, AES_BLOCK_SIZE);
memcpy(tmp2, out, AES_BLOCK_SIZE);
for (n = 0; n < AES_BLOCK_SIZE; ++n)
tmp[n] ^= iv2[n];
AES_decrypt(tmp, out, key);
for (n = 0; n < AES_BLOCK_SIZE; ++n)
out[n] ^= iv[n];
memcpy(tmp3, tmp2, AES_BLOCK_SIZE);
iv = tmp3;
iv2 = out;
len -= AES_BLOCK_SIZE;
in += AES_BLOCK_SIZE;
out += AES_BLOCK_SIZE;
}
}
}
@@ -0,0 +1,89 @@
/* crypto/aes/aes.h */
/* ====================================================================
* Copyright (c) 1998-2002 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
* openssl-core@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.
* ====================================================================
*
*/
#ifndef HEADER_AES_LOCL_H
# define HEADER_AES_LOCL_H
# include <openssl/e_os2.h>
# ifdef OPENSSL_NO_AES
# error AES is disabled.
# endif
# include <stdio.h>
# include <stdlib.h>
# include <string.h>
# if defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_AMD64) || defined(_M_X64))
# define SWAP(x) (_lrotl(x, 8) & 0x00ff00ff | _lrotr(x, 8) & 0xff00ff00)
# define GETU32(p) SWAP(*((u32 *)(p)))
# define PUTU32(ct, st) { *((u32 *)(ct)) = SWAP((st)); }
# else
# define GETU32(pt) (((u32)(pt)[0] << 24) ^ ((u32)(pt)[1] << 16) ^ ((u32)(pt)[2] << 8) ^ ((u32)(pt)[3]))
# define PUTU32(ct, st) { (ct)[0] = (u8)((st) >> 24); (ct)[1] = (u8)((st) >> 16); (ct)[2] = (u8)((st) >> 8); (ct)[3] = (u8)(st); }
# endif
# ifdef AES_LONG
typedef unsigned long u32;
# else
typedef unsigned int u32;
# endif
typedef unsigned short u16;
typedef unsigned char u8;
# define MAXKC (256/32)
# define MAXKB (256/8)
# define MAXNR 14
/* This controls loop-unrolling in aes_core.c */
# undef FULL_UNROLL
#endif /* !HEADER_AES_LOCL_H */
@@ -0,0 +1,87 @@
/* crypto/aes/aes_misc.c */
/* ====================================================================
* Copyright (c) 1998-2002 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
* openssl-core@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.
* ====================================================================
*
*/
#include <sys/types.h>
#include <openssl/opensslv.h>
#include <openssl/crypto.h>
#include <openssl/aes.h>
#include "aes_locl.h"
const char AES_version[] = "AES" OPENSSL_VERSION_PTEXT;
const char *AES_options(void)
{
#ifdef FULL_UNROLL
return "aes(full)";
#else
return "aes(partial)";
#endif
}
/* FIPS wrapper functions to block low level AES calls in FIPS mode */
int AES_set_encrypt_key(const unsigned char *userKey, const int bits,
AES_KEY *key)
{
#ifdef OPENSSL_FIPS
fips_cipher_abort(AES);
#endif
return private_AES_set_encrypt_key(userKey, bits, key);
}
int AES_set_decrypt_key(const unsigned char *userKey, const int bits,
AES_KEY *key)
{
#ifdef OPENSSL_FIPS
fips_cipher_abort(AES);
#endif
return private_AES_set_decrypt_key(userKey, bits, key);
}
@@ -0,0 +1,62 @@
/* crypto/aes/aes_ofb.c */
/* ====================================================================
* Copyright (c) 2002-2006 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
* openssl-core@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.
* ====================================================================
*
*/
#include <sys/types.h>
#include <openssl/aes.h>
#include <openssl/modes.h>
void AES_ofb128_encrypt(const unsigned char *in, unsigned char *out,
size_t length, const AES_KEY *key,
unsigned char *ivec, int *num)
{
CRYPTO_ofb128_encrypt(in, out, length, key, ivec, num,
(block128_f) AES_encrypt);
}
@@ -0,0 +1,72 @@
/* crypto/aes/aes_wrap.c */
/*
* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
* project.
*/
/* ====================================================================
* Copyright (c) 2008 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.
* ====================================================================
*/
#include "cryptlib.h"
#include <openssl/aes.h>
#include <openssl/modes.h>
int AES_wrap_key(AES_KEY *key, const unsigned char *iv,
unsigned char *out,
const unsigned char *in, unsigned int inlen)
{
return CRYPTO_128_wrap(key, iv, out, in, inlen, (block128_f) AES_encrypt);
}
int AES_unwrap_key(AES_KEY *key, const unsigned char *iv,
unsigned char *out,
const unsigned char *in, unsigned int inlen)
{
return CRYPTO_128_unwrap(key, iv, out, in, inlen,
(block128_f) AES_decrypt);
}
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,754 @@
#include "../arm_arch.h"
#if __ARM_MAX_ARCH__>=7
.text
.arch armv7-a
.fpu neon
.code 32
.align 5
rcon:
.long 0x01,0x01,0x01,0x01
.long 0x0c0f0e0d,0x0c0f0e0d,0x0c0f0e0d,0x0c0f0e0d @ rotate-n-splat
.long 0x1b,0x1b,0x1b,0x1b
.globl aes_v8_set_encrypt_key
.type aes_v8_set_encrypt_key,%function
.align 5
aes_v8_set_encrypt_key:
.Lenc_key:
mov r3,#-1
cmp r0,#0
beq .Lenc_key_abort
cmp r2,#0
beq .Lenc_key_abort
mov r3,#-2
cmp r1,#128
blt .Lenc_key_abort
cmp r1,#256
bgt .Lenc_key_abort
tst r1,#0x3f
bne .Lenc_key_abort
adr r3,rcon
cmp r1,#192
veor q0,q0,q0
vld1.8 {q3},[r0]!
mov r1,#8 @ reuse r1
vld1.32 {q1,q2},[r3]!
blt .Loop128
beq .L192
b .L256
.align 4
.Loop128:
vtbl.8 d20,{q3},d4
vtbl.8 d21,{q3},d5
vext.8 q9,q0,q3,#12
vst1.32 {q3},[r2]!
.byte 0x00,0x43,0xf0,0xf3 @ aese q10,q0
subs r1,r1,#1
veor q3,q3,q9
vext.8 q9,q0,q9,#12
veor q3,q3,q9
vext.8 q9,q0,q9,#12
veor q10,q10,q1
veor q3,q3,q9
vshl.u8 q1,q1,#1
veor q3,q3,q10
bne .Loop128
vld1.32 {q1},[r3]
vtbl.8 d20,{q3},d4
vtbl.8 d21,{q3},d5
vext.8 q9,q0,q3,#12
vst1.32 {q3},[r2]!
.byte 0x00,0x43,0xf0,0xf3 @ aese q10,q0
veor q3,q3,q9
vext.8 q9,q0,q9,#12
veor q3,q3,q9
vext.8 q9,q0,q9,#12
veor q10,q10,q1
veor q3,q3,q9
vshl.u8 q1,q1,#1
veor q3,q3,q10
vtbl.8 d20,{q3},d4
vtbl.8 d21,{q3},d5
vext.8 q9,q0,q3,#12
vst1.32 {q3},[r2]!
.byte 0x00,0x43,0xf0,0xf3 @ aese q10,q0
veor q3,q3,q9
vext.8 q9,q0,q9,#12
veor q3,q3,q9
vext.8 q9,q0,q9,#12
veor q10,q10,q1
veor q3,q3,q9
veor q3,q3,q10
vst1.32 {q3},[r2]
add r2,r2,#0x50
mov r12,#10
b .Ldone
.align 4
.L192:
vld1.8 {d16},[r0]!
vmov.i8 q10,#8 @ borrow q10
vst1.32 {q3},[r2]!
vsub.i8 q2,q2,q10 @ adjust the mask
.Loop192:
vtbl.8 d20,{q8},d4
vtbl.8 d21,{q8},d5
vext.8 q9,q0,q3,#12
vst1.32 {d16},[r2]!
.byte 0x00,0x43,0xf0,0xf3 @ aese q10,q0
subs r1,r1,#1
veor q3,q3,q9
vext.8 q9,q0,q9,#12
veor q3,q3,q9
vext.8 q9,q0,q9,#12
veor q3,q3,q9
vdup.32 q9,d7[1]
veor q9,q9,q8
veor q10,q10,q1
vext.8 q8,q0,q8,#12
vshl.u8 q1,q1,#1
veor q8,q8,q9
veor q3,q3,q10
veor q8,q8,q10
vst1.32 {q3},[r2]!
bne .Loop192
mov r12,#12
add r2,r2,#0x20
b .Ldone
.align 4
.L256:
vld1.8 {q8},[r0]
mov r1,#7
mov r12,#14
vst1.32 {q3},[r2]!
.Loop256:
vtbl.8 d20,{q8},d4
vtbl.8 d21,{q8},d5
vext.8 q9,q0,q3,#12
vst1.32 {q8},[r2]!
.byte 0x00,0x43,0xf0,0xf3 @ aese q10,q0
subs r1,r1,#1
veor q3,q3,q9
vext.8 q9,q0,q9,#12
veor q3,q3,q9
vext.8 q9,q0,q9,#12
veor q10,q10,q1
veor q3,q3,q9
vshl.u8 q1,q1,#1
veor q3,q3,q10
vst1.32 {q3},[r2]!
beq .Ldone
vdup.32 q10,d7[1]
vext.8 q9,q0,q8,#12
.byte 0x00,0x43,0xf0,0xf3 @ aese q10,q0
veor q8,q8,q9
vext.8 q9,q0,q9,#12
veor q8,q8,q9
vext.8 q9,q0,q9,#12
veor q8,q8,q9
veor q8,q8,q10
b .Loop256
.Ldone:
str r12,[r2]
mov r3,#0
.Lenc_key_abort:
mov r0,r3 @ return value
bx lr
.size aes_v8_set_encrypt_key,.-aes_v8_set_encrypt_key
.globl aes_v8_set_decrypt_key
.type aes_v8_set_decrypt_key,%function
.align 5
aes_v8_set_decrypt_key:
stmdb sp!,{r4,lr}
bl .Lenc_key
cmp r0,#0
bne .Ldec_key_abort
sub r2,r2,#240 @ restore original r2
mov r4,#-16
add r0,r2,r12,lsl#4 @ end of key schedule
vld1.32 {q0},[r2]
vld1.32 {q1},[r0]
vst1.32 {q0},[r0],r4
vst1.32 {q1},[r2]!
.Loop_imc:
vld1.32 {q0},[r2]
vld1.32 {q1},[r0]
.byte 0xc0,0x03,0xb0,0xf3 @ aesimc q0,q0
.byte 0xc2,0x23,0xb0,0xf3 @ aesimc q1,q1
vst1.32 {q0},[r0],r4
vst1.32 {q1},[r2]!
cmp r0,r2
bhi .Loop_imc
vld1.32 {q0},[r2]
.byte 0xc0,0x03,0xb0,0xf3 @ aesimc q0,q0
vst1.32 {q0},[r0]
eor r0,r0,r0 @ return value
.Ldec_key_abort:
ldmia sp!,{r4,pc}
.size aes_v8_set_decrypt_key,.-aes_v8_set_decrypt_key
.globl aes_v8_encrypt
.type aes_v8_encrypt,%function
.align 5
aes_v8_encrypt:
ldr r3,[r2,#240]
vld1.32 {q0},[r2]!
vld1.8 {q2},[r0]
sub r3,r3,#2
vld1.32 {q1},[r2]!
.Loop_enc:
.byte 0x00,0x43,0xb0,0xf3 @ aese q2,q0
.byte 0x84,0x43,0xb0,0xf3 @ aesmc q2,q2
vld1.32 {q0},[r2]!
subs r3,r3,#2
.byte 0x02,0x43,0xb0,0xf3 @ aese q2,q1
.byte 0x84,0x43,0xb0,0xf3 @ aesmc q2,q2
vld1.32 {q1},[r2]!
bgt .Loop_enc
.byte 0x00,0x43,0xb0,0xf3 @ aese q2,q0
.byte 0x84,0x43,0xb0,0xf3 @ aesmc q2,q2
vld1.32 {q0},[r2]
.byte 0x02,0x43,0xb0,0xf3 @ aese q2,q1
veor q2,q2,q0
vst1.8 {q2},[r1]
bx lr
.size aes_v8_encrypt,.-aes_v8_encrypt
.globl aes_v8_decrypt
.type aes_v8_decrypt,%function
.align 5
aes_v8_decrypt:
ldr r3,[r2,#240]
vld1.32 {q0},[r2]!
vld1.8 {q2},[r0]
sub r3,r3,#2
vld1.32 {q1},[r2]!
.Loop_dec:
.byte 0x40,0x43,0xb0,0xf3 @ aesd q2,q0
.byte 0xc4,0x43,0xb0,0xf3 @ aesimc q2,q2
vld1.32 {q0},[r2]!
subs r3,r3,#2
.byte 0x42,0x43,0xb0,0xf3 @ aesd q2,q1
.byte 0xc4,0x43,0xb0,0xf3 @ aesimc q2,q2
vld1.32 {q1},[r2]!
bgt .Loop_dec
.byte 0x40,0x43,0xb0,0xf3 @ aesd q2,q0
.byte 0xc4,0x43,0xb0,0xf3 @ aesimc q2,q2
vld1.32 {q0},[r2]
.byte 0x42,0x43,0xb0,0xf3 @ aesd q2,q1
veor q2,q2,q0
vst1.8 {q2},[r1]
bx lr
.size aes_v8_decrypt,.-aes_v8_decrypt
.globl aes_v8_cbc_encrypt
.type aes_v8_cbc_encrypt,%function
.align 5
aes_v8_cbc_encrypt:
mov ip,sp
stmdb sp!,{r4-r8,lr}
vstmdb sp!,{d8-d15} @ ABI specification says so
ldmia ip,{r4-r5} @ load remaining args
subs r2,r2,#16
mov r8,#16
blo .Lcbc_abort
moveq r8,#0
cmp r5,#0 @ en- or decrypting?
ldr r5,[r3,#240]
and r2,r2,#-16
vld1.8 {q6},[r4]
vld1.8 {q0},[r0],r8
vld1.32 {q8-q9},[r3] @ load key schedule...
sub r5,r5,#6
add r7,r3,r5,lsl#4 @ pointer to last 7 round keys
sub r5,r5,#2
vld1.32 {q10-q11},[r7]!
vld1.32 {q12-q13},[r7]!
vld1.32 {q14-q15},[r7]!
vld1.32 {q7},[r7]
add r7,r3,#32
mov r6,r5
beq .Lcbc_dec
cmp r5,#2
veor q0,q0,q6
veor q5,q8,q7
beq .Lcbc_enc128
vld1.32 {q2-q3},[r7]
add r7,r3,#16
add r6,r3,#16*4
add r12,r3,#16*5
.byte 0x20,0x03,0xb0,0xf3 @ aese q0,q8
.byte 0x80,0x03,0xb0,0xf3 @ aesmc q0,q0
add r14,r3,#16*6
add r3,r3,#16*7
b .Lenter_cbc_enc
.align 4
.Loop_cbc_enc:
.byte 0x20,0x03,0xb0,0xf3 @ aese q0,q8
.byte 0x80,0x03,0xb0,0xf3 @ aesmc q0,q0
vst1.8 {q6},[r1]!
.Lenter_cbc_enc:
.byte 0x22,0x03,0xb0,0xf3 @ aese q0,q9
.byte 0x80,0x03,0xb0,0xf3 @ aesmc q0,q0
.byte 0x04,0x03,0xb0,0xf3 @ aese q0,q2
.byte 0x80,0x03,0xb0,0xf3 @ aesmc q0,q0
vld1.32 {q8},[r6]
cmp r5,#4
.byte 0x06,0x03,0xb0,0xf3 @ aese q0,q3
.byte 0x80,0x03,0xb0,0xf3 @ aesmc q0,q0
vld1.32 {q9},[r12]
beq .Lcbc_enc192
.byte 0x20,0x03,0xb0,0xf3 @ aese q0,q8
.byte 0x80,0x03,0xb0,0xf3 @ aesmc q0,q0
vld1.32 {q8},[r14]
.byte 0x22,0x03,0xb0,0xf3 @ aese q0,q9
.byte 0x80,0x03,0xb0,0xf3 @ aesmc q0,q0
vld1.32 {q9},[r3]
nop
.Lcbc_enc192:
.byte 0x20,0x03,0xb0,0xf3 @ aese q0,q8
.byte 0x80,0x03,0xb0,0xf3 @ aesmc q0,q0
subs r2,r2,#16
.byte 0x22,0x03,0xb0,0xf3 @ aese q0,q9
.byte 0x80,0x03,0xb0,0xf3 @ aesmc q0,q0
moveq r8,#0
.byte 0x24,0x03,0xb0,0xf3 @ aese q0,q10
.byte 0x80,0x03,0xb0,0xf3 @ aesmc q0,q0
.byte 0x26,0x03,0xb0,0xf3 @ aese q0,q11
.byte 0x80,0x03,0xb0,0xf3 @ aesmc q0,q0
vld1.8 {q8},[r0],r8
.byte 0x28,0x03,0xb0,0xf3 @ aese q0,q12
.byte 0x80,0x03,0xb0,0xf3 @ aesmc q0,q0
veor q8,q8,q5
.byte 0x2a,0x03,0xb0,0xf3 @ aese q0,q13
.byte 0x80,0x03,0xb0,0xf3 @ aesmc q0,q0
vld1.32 {q9},[r7] @ re-pre-load rndkey[1]
.byte 0x2c,0x03,0xb0,0xf3 @ aese q0,q14
.byte 0x80,0x03,0xb0,0xf3 @ aesmc q0,q0
.byte 0x2e,0x03,0xb0,0xf3 @ aese q0,q15
veor q6,q0,q7
bhs .Loop_cbc_enc
vst1.8 {q6},[r1]!
b .Lcbc_done
.align 5
.Lcbc_enc128:
vld1.32 {q2-q3},[r7]
.byte 0x20,0x03,0xb0,0xf3 @ aese q0,q8
.byte 0x80,0x03,0xb0,0xf3 @ aesmc q0,q0
b .Lenter_cbc_enc128
.Loop_cbc_enc128:
.byte 0x20,0x03,0xb0,0xf3 @ aese q0,q8
.byte 0x80,0x03,0xb0,0xf3 @ aesmc q0,q0
vst1.8 {q6},[r1]!
.Lenter_cbc_enc128:
.byte 0x22,0x03,0xb0,0xf3 @ aese q0,q9
.byte 0x80,0x03,0xb0,0xf3 @ aesmc q0,q0
subs r2,r2,#16
.byte 0x04,0x03,0xb0,0xf3 @ aese q0,q2
.byte 0x80,0x03,0xb0,0xf3 @ aesmc q0,q0
moveq r8,#0
.byte 0x06,0x03,0xb0,0xf3 @ aese q0,q3
.byte 0x80,0x03,0xb0,0xf3 @ aesmc q0,q0
.byte 0x24,0x03,0xb0,0xf3 @ aese q0,q10
.byte 0x80,0x03,0xb0,0xf3 @ aesmc q0,q0
.byte 0x26,0x03,0xb0,0xf3 @ aese q0,q11
.byte 0x80,0x03,0xb0,0xf3 @ aesmc q0,q0
vld1.8 {q8},[r0],r8
.byte 0x28,0x03,0xb0,0xf3 @ aese q0,q12
.byte 0x80,0x03,0xb0,0xf3 @ aesmc q0,q0
.byte 0x2a,0x03,0xb0,0xf3 @ aese q0,q13
.byte 0x80,0x03,0xb0,0xf3 @ aesmc q0,q0
.byte 0x2c,0x03,0xb0,0xf3 @ aese q0,q14
.byte 0x80,0x03,0xb0,0xf3 @ aesmc q0,q0
veor q8,q8,q5
.byte 0x2e,0x03,0xb0,0xf3 @ aese q0,q15
veor q6,q0,q7
bhs .Loop_cbc_enc128
vst1.8 {q6},[r1]!
b .Lcbc_done
.align 5
.Lcbc_dec:
vld1.8 {q10},[r0]!
subs r2,r2,#32 @ bias
add r6,r5,#2
vorr q3,q0,q0
vorr q1,q0,q0
vorr q11,q10,q10
blo .Lcbc_dec_tail
vorr q1,q10,q10
vld1.8 {q10},[r0]!
vorr q2,q0,q0
vorr q3,q1,q1
vorr q11,q10,q10
.Loop3x_cbc_dec:
.byte 0x60,0x03,0xb0,0xf3 @ aesd q0,q8
.byte 0xc0,0x03,0xb0,0xf3 @ aesimc q0,q0
.byte 0x60,0x23,0xb0,0xf3 @ aesd q1,q8
.byte 0xc2,0x23,0xb0,0xf3 @ aesimc q1,q1
.byte 0x60,0x43,0xf0,0xf3 @ aesd q10,q8
.byte 0xe4,0x43,0xf0,0xf3 @ aesimc q10,q10
vld1.32 {q8},[r7]!
subs r6,r6,#2
.byte 0x62,0x03,0xb0,0xf3 @ aesd q0,q9
.byte 0xc0,0x03,0xb0,0xf3 @ aesimc q0,q0
.byte 0x62,0x23,0xb0,0xf3 @ aesd q1,q9
.byte 0xc2,0x23,0xb0,0xf3 @ aesimc q1,q1
.byte 0x62,0x43,0xf0,0xf3 @ aesd q10,q9
.byte 0xe4,0x43,0xf0,0xf3 @ aesimc q10,q10
vld1.32 {q9},[r7]!
bgt .Loop3x_cbc_dec
.byte 0x60,0x03,0xb0,0xf3 @ aesd q0,q8
.byte 0xc0,0x03,0xb0,0xf3 @ aesimc q0,q0
.byte 0x60,0x23,0xb0,0xf3 @ aesd q1,q8
.byte 0xc2,0x23,0xb0,0xf3 @ aesimc q1,q1
.byte 0x60,0x43,0xf0,0xf3 @ aesd q10,q8
.byte 0xe4,0x43,0xf0,0xf3 @ aesimc q10,q10
veor q4,q6,q7
subs r2,r2,#0x30
veor q5,q2,q7
movlo r6,r2 @ r6, r6, is zero at this point
.byte 0x62,0x03,0xb0,0xf3 @ aesd q0,q9
.byte 0xc0,0x03,0xb0,0xf3 @ aesimc q0,q0
.byte 0x62,0x23,0xb0,0xf3 @ aesd q1,q9
.byte 0xc2,0x23,0xb0,0xf3 @ aesimc q1,q1
.byte 0x62,0x43,0xf0,0xf3 @ aesd q10,q9
.byte 0xe4,0x43,0xf0,0xf3 @ aesimc q10,q10
veor q9,q3,q7
add r0,r0,r6 @ r0 is adjusted in such way that
@ at exit from the loop q1-q10
@ are loaded with last "words"
vorr q6,q11,q11
mov r7,r3
.byte 0x68,0x03,0xb0,0xf3 @ aesd q0,q12
.byte 0xc0,0x03,0xb0,0xf3 @ aesimc q0,q0
.byte 0x68,0x23,0xb0,0xf3 @ aesd q1,q12
.byte 0xc2,0x23,0xb0,0xf3 @ aesimc q1,q1
.byte 0x68,0x43,0xf0,0xf3 @ aesd q10,q12
.byte 0xe4,0x43,0xf0,0xf3 @ aesimc q10,q10
vld1.8 {q2},[r0]!
.byte 0x6a,0x03,0xb0,0xf3 @ aesd q0,q13
.byte 0xc0,0x03,0xb0,0xf3 @ aesimc q0,q0
.byte 0x6a,0x23,0xb0,0xf3 @ aesd q1,q13
.byte 0xc2,0x23,0xb0,0xf3 @ aesimc q1,q1
.byte 0x6a,0x43,0xf0,0xf3 @ aesd q10,q13
.byte 0xe4,0x43,0xf0,0xf3 @ aesimc q10,q10
vld1.8 {q3},[r0]!
.byte 0x6c,0x03,0xb0,0xf3 @ aesd q0,q14
.byte 0xc0,0x03,0xb0,0xf3 @ aesimc q0,q0
.byte 0x6c,0x23,0xb0,0xf3 @ aesd q1,q14
.byte 0xc2,0x23,0xb0,0xf3 @ aesimc q1,q1
.byte 0x6c,0x43,0xf0,0xf3 @ aesd q10,q14
.byte 0xe4,0x43,0xf0,0xf3 @ aesimc q10,q10
vld1.8 {q11},[r0]!
.byte 0x6e,0x03,0xb0,0xf3 @ aesd q0,q15
.byte 0x6e,0x23,0xb0,0xf3 @ aesd q1,q15
.byte 0x6e,0x43,0xf0,0xf3 @ aesd q10,q15
vld1.32 {q8},[r7]! @ re-pre-load rndkey[0]
add r6,r5,#2
veor q4,q4,q0
veor q5,q5,q1
veor q10,q10,q9
vld1.32 {q9},[r7]! @ re-pre-load rndkey[1]
vst1.8 {q4},[r1]!
vorr q0,q2,q2
vst1.8 {q5},[r1]!
vorr q1,q3,q3
vst1.8 {q10},[r1]!
vorr q10,q11,q11
bhs .Loop3x_cbc_dec
cmn r2,#0x30
beq .Lcbc_done
nop
.Lcbc_dec_tail:
.byte 0x60,0x23,0xb0,0xf3 @ aesd q1,q8
.byte 0xc2,0x23,0xb0,0xf3 @ aesimc q1,q1
.byte 0x60,0x43,0xf0,0xf3 @ aesd q10,q8
.byte 0xe4,0x43,0xf0,0xf3 @ aesimc q10,q10
vld1.32 {q8},[r7]!
subs r6,r6,#2
.byte 0x62,0x23,0xb0,0xf3 @ aesd q1,q9
.byte 0xc2,0x23,0xb0,0xf3 @ aesimc q1,q1
.byte 0x62,0x43,0xf0,0xf3 @ aesd q10,q9
.byte 0xe4,0x43,0xf0,0xf3 @ aesimc q10,q10
vld1.32 {q9},[r7]!
bgt .Lcbc_dec_tail
.byte 0x60,0x23,0xb0,0xf3 @ aesd q1,q8
.byte 0xc2,0x23,0xb0,0xf3 @ aesimc q1,q1
.byte 0x60,0x43,0xf0,0xf3 @ aesd q10,q8
.byte 0xe4,0x43,0xf0,0xf3 @ aesimc q10,q10
.byte 0x62,0x23,0xb0,0xf3 @ aesd q1,q9
.byte 0xc2,0x23,0xb0,0xf3 @ aesimc q1,q1
.byte 0x62,0x43,0xf0,0xf3 @ aesd q10,q9
.byte 0xe4,0x43,0xf0,0xf3 @ aesimc q10,q10
.byte 0x68,0x23,0xb0,0xf3 @ aesd q1,q12
.byte 0xc2,0x23,0xb0,0xf3 @ aesimc q1,q1
.byte 0x68,0x43,0xf0,0xf3 @ aesd q10,q12
.byte 0xe4,0x43,0xf0,0xf3 @ aesimc q10,q10
cmn r2,#0x20
.byte 0x6a,0x23,0xb0,0xf3 @ aesd q1,q13
.byte 0xc2,0x23,0xb0,0xf3 @ aesimc q1,q1
.byte 0x6a,0x43,0xf0,0xf3 @ aesd q10,q13
.byte 0xe4,0x43,0xf0,0xf3 @ aesimc q10,q10
veor q5,q6,q7
.byte 0x6c,0x23,0xb0,0xf3 @ aesd q1,q14
.byte 0xc2,0x23,0xb0,0xf3 @ aesimc q1,q1
.byte 0x6c,0x43,0xf0,0xf3 @ aesd q10,q14
.byte 0xe4,0x43,0xf0,0xf3 @ aesimc q10,q10
veor q9,q3,q7
.byte 0x6e,0x23,0xb0,0xf3 @ aesd q1,q15
.byte 0x6e,0x43,0xf0,0xf3 @ aesd q10,q15
beq .Lcbc_dec_one
veor q5,q5,q1
veor q9,q9,q10
vorr q6,q11,q11
vst1.8 {q5},[r1]!
vst1.8 {q9},[r1]!
b .Lcbc_done
.Lcbc_dec_one:
veor q5,q5,q10
vorr q6,q11,q11
vst1.8 {q5},[r1]!
.Lcbc_done:
vst1.8 {q6},[r4]
.Lcbc_abort:
vldmia sp!,{d8-d15}
ldmia sp!,{r4-r8,pc}
.size aes_v8_cbc_encrypt,.-aes_v8_cbc_encrypt
.globl aes_v8_ctr32_encrypt_blocks
.type aes_v8_ctr32_encrypt_blocks,%function
.align 5
aes_v8_ctr32_encrypt_blocks:
mov ip,sp
stmdb sp!,{r4-r10,lr}
vstmdb sp!,{d8-d15} @ ABI specification says so
ldr r4, [ip] @ load remaining arg
ldr r5,[r3,#240]
ldr r8, [r4, #12]
vld1.32 {q0},[r4]
vld1.32 {q8-q9},[r3] @ load key schedule...
sub r5,r5,#4
mov r12,#16
cmp r2,#2
add r7,r3,r5,lsl#4 @ pointer to last 5 round keys
sub r5,r5,#2
vld1.32 {q12-q13},[r7]!
vld1.32 {q14-q15},[r7]!
vld1.32 {q7},[r7]
add r7,r3,#32
mov r6,r5
movlo r12,#0
#ifndef __ARMEB__
rev r8, r8
#endif
vorr q1,q0,q0
add r10, r8, #1
vorr q10,q0,q0
add r8, r8, #2
vorr q6,q0,q0
rev r10, r10
vmov.32 d3[1],r10
bls .Lctr32_tail
rev r12, r8
sub r2,r2,#3 @ bias
vmov.32 d21[1],r12
b .Loop3x_ctr32
.align 4
.Loop3x_ctr32:
.byte 0x20,0x03,0xb0,0xf3 @ aese q0,q8
.byte 0x80,0x03,0xb0,0xf3 @ aesmc q0,q0
.byte 0x20,0x23,0xb0,0xf3 @ aese q1,q8
.byte 0x82,0x23,0xb0,0xf3 @ aesmc q1,q1
.byte 0x20,0x43,0xf0,0xf3 @ aese q10,q8
.byte 0xa4,0x43,0xf0,0xf3 @ aesmc q10,q10
vld1.32 {q8},[r7]!
subs r6,r6,#2
.byte 0x22,0x03,0xb0,0xf3 @ aese q0,q9
.byte 0x80,0x03,0xb0,0xf3 @ aesmc q0,q0
.byte 0x22,0x23,0xb0,0xf3 @ aese q1,q9
.byte 0x82,0x23,0xb0,0xf3 @ aesmc q1,q1
.byte 0x22,0x43,0xf0,0xf3 @ aese q10,q9
.byte 0xa4,0x43,0xf0,0xf3 @ aesmc q10,q10
vld1.32 {q9},[r7]!
bgt .Loop3x_ctr32
.byte 0x20,0x03,0xb0,0xf3 @ aese q0,q8
.byte 0x80,0x83,0xb0,0xf3 @ aesmc q4,q0
.byte 0x20,0x23,0xb0,0xf3 @ aese q1,q8
.byte 0x82,0xa3,0xb0,0xf3 @ aesmc q5,q1
vld1.8 {q2},[r0]!
vorr q0,q6,q6
.byte 0x20,0x43,0xf0,0xf3 @ aese q10,q8
.byte 0xa4,0x43,0xf0,0xf3 @ aesmc q10,q10
vld1.8 {q3},[r0]!
vorr q1,q6,q6
.byte 0x22,0x83,0xb0,0xf3 @ aese q4,q9
.byte 0x88,0x83,0xb0,0xf3 @ aesmc q4,q4
.byte 0x22,0xa3,0xb0,0xf3 @ aese q5,q9
.byte 0x8a,0xa3,0xb0,0xf3 @ aesmc q5,q5
vld1.8 {q11},[r0]!
mov r7,r3
.byte 0x22,0x43,0xf0,0xf3 @ aese q10,q9
.byte 0xa4,0x23,0xf0,0xf3 @ aesmc q9,q10
vorr q10,q6,q6
add r9,r8,#1
.byte 0x28,0x83,0xb0,0xf3 @ aese q4,q12
.byte 0x88,0x83,0xb0,0xf3 @ aesmc q4,q4
.byte 0x28,0xa3,0xb0,0xf3 @ aese q5,q12
.byte 0x8a,0xa3,0xb0,0xf3 @ aesmc q5,q5
veor q2,q2,q7
add r10,r8,#2
.byte 0x28,0x23,0xf0,0xf3 @ aese q9,q12
.byte 0xa2,0x23,0xf0,0xf3 @ aesmc q9,q9
veor q3,q3,q7
add r8,r8,#3
.byte 0x2a,0x83,0xb0,0xf3 @ aese q4,q13
.byte 0x88,0x83,0xb0,0xf3 @ aesmc q4,q4
.byte 0x2a,0xa3,0xb0,0xf3 @ aese q5,q13
.byte 0x8a,0xa3,0xb0,0xf3 @ aesmc q5,q5
veor q11,q11,q7
rev r9,r9
.byte 0x2a,0x23,0xf0,0xf3 @ aese q9,q13
.byte 0xa2,0x23,0xf0,0xf3 @ aesmc q9,q9
vmov.32 d1[1], r9
rev r10,r10
.byte 0x2c,0x83,0xb0,0xf3 @ aese q4,q14
.byte 0x88,0x83,0xb0,0xf3 @ aesmc q4,q4
.byte 0x2c,0xa3,0xb0,0xf3 @ aese q5,q14
.byte 0x8a,0xa3,0xb0,0xf3 @ aesmc q5,q5
vmov.32 d3[1], r10
rev r12,r8
.byte 0x2c,0x23,0xf0,0xf3 @ aese q9,q14
.byte 0xa2,0x23,0xf0,0xf3 @ aesmc q9,q9
vmov.32 d21[1], r12
subs r2,r2,#3
.byte 0x2e,0x83,0xb0,0xf3 @ aese q4,q15
.byte 0x2e,0xa3,0xb0,0xf3 @ aese q5,q15
.byte 0x2e,0x23,0xf0,0xf3 @ aese q9,q15
veor q2,q2,q4
vld1.32 {q8},[r7]! @ re-pre-load rndkey[0]
vst1.8 {q2},[r1]!
veor q3,q3,q5
mov r6,r5
vst1.8 {q3},[r1]!
veor q11,q11,q9
vld1.32 {q9},[r7]! @ re-pre-load rndkey[1]
vst1.8 {q11},[r1]!
bhs .Loop3x_ctr32
adds r2,r2,#3
beq .Lctr32_done
cmp r2,#1
mov r12,#16
moveq r12,#0
.Lctr32_tail:
.byte 0x20,0x03,0xb0,0xf3 @ aese q0,q8
.byte 0x80,0x03,0xb0,0xf3 @ aesmc q0,q0
.byte 0x20,0x23,0xb0,0xf3 @ aese q1,q8
.byte 0x82,0x23,0xb0,0xf3 @ aesmc q1,q1
vld1.32 {q8},[r7]!
subs r6,r6,#2
.byte 0x22,0x03,0xb0,0xf3 @ aese q0,q9
.byte 0x80,0x03,0xb0,0xf3 @ aesmc q0,q0
.byte 0x22,0x23,0xb0,0xf3 @ aese q1,q9
.byte 0x82,0x23,0xb0,0xf3 @ aesmc q1,q1
vld1.32 {q9},[r7]!
bgt .Lctr32_tail
.byte 0x20,0x03,0xb0,0xf3 @ aese q0,q8
.byte 0x80,0x03,0xb0,0xf3 @ aesmc q0,q0
.byte 0x20,0x23,0xb0,0xf3 @ aese q1,q8
.byte 0x82,0x23,0xb0,0xf3 @ aesmc q1,q1
.byte 0x22,0x03,0xb0,0xf3 @ aese q0,q9
.byte 0x80,0x03,0xb0,0xf3 @ aesmc q0,q0
.byte 0x22,0x23,0xb0,0xf3 @ aese q1,q9
.byte 0x82,0x23,0xb0,0xf3 @ aesmc q1,q1
vld1.8 {q2},[r0],r12
.byte 0x28,0x03,0xb0,0xf3 @ aese q0,q12
.byte 0x80,0x03,0xb0,0xf3 @ aesmc q0,q0
.byte 0x28,0x23,0xb0,0xf3 @ aese q1,q12
.byte 0x82,0x23,0xb0,0xf3 @ aesmc q1,q1
vld1.8 {q3},[r0]
.byte 0x2a,0x03,0xb0,0xf3 @ aese q0,q13
.byte 0x80,0x03,0xb0,0xf3 @ aesmc q0,q0
.byte 0x2a,0x23,0xb0,0xf3 @ aese q1,q13
.byte 0x82,0x23,0xb0,0xf3 @ aesmc q1,q1
veor q2,q2,q7
.byte 0x2c,0x03,0xb0,0xf3 @ aese q0,q14
.byte 0x80,0x03,0xb0,0xf3 @ aesmc q0,q0
.byte 0x2c,0x23,0xb0,0xf3 @ aese q1,q14
.byte 0x82,0x23,0xb0,0xf3 @ aesmc q1,q1
veor q3,q3,q7
.byte 0x2e,0x03,0xb0,0xf3 @ aese q0,q15
.byte 0x2e,0x23,0xb0,0xf3 @ aese q1,q15
cmp r2,#1
veor q2,q2,q0
veor q3,q3,q1
vst1.8 {q2},[r1]!
beq .Lctr32_done
vst1.8 {q3},[r1]
.Lctr32_done:
vldmia sp!,{d8-d15}
ldmia sp!,{r4-r10,pc}
.size aes_v8_ctr32_encrypt_blocks,.-aes_v8_ctr32_encrypt_blocks
#endif
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,448 @@
/*-----------------------------------------------------------------------------
// Licensed Materials - Property of IBM
// OCO Source Materials
// ICC
// (C) Copyright IBM Corp. 2002,2007
// The source code for this program is not published or otherwise
// divested of its trade secrets, irrespective of what has been
// deposited with the U.S. Copyright Office.
//
// File, Component, Release:
// icc_test/hex_utils.c, ICC_TEST, icc_8.0, icc8.0_070119
//
// Version: 1.8
//
// Date and Time File was last checked in: 07/06/06 18:34:05
// Date and Time File was extracted/checked out: 07/08/19 20:01:25
//
// Description: hex utility functions
//
// Authors: Peter Waltenberg
//
// Authors Defect (D) or Feature (F) and Number
// ------- ------------------------------------
// PTW D39500 Fixed bug in read_rawhex (found while debugging HMAC test cases)
// PTW D39650 Added logical operators on hex strings
// PTW D39660 Compiler warnings
// PTW Db1775_1 Compiler errors. (malloc/calloc return values)
// PTW D39919 Refactor hex manipulation routines
//---------------------------------------------------------------------------*/
/*
Convert between binary and hexadecimal data
This file has NO dependencies on OpenSSL/ICC
etc
*/
#if !defined(DEMO_CODE)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#if defined(WIN32) || defined(__OS2__)
#include <io.h>
#else
#include <unistd.h>
#endif
#endif /* ! DEMO_CODE */
#include "hex_utils.h"
/* Note: This won't cope with arbirarilly large IV's (i.e. VERY large keys)
I allocate enough for an 8kbit key below, but if you use even
larger keys fix this
*/
#define IVBUFLEN 512 * 16
#define EKEYLH "<keylen>"
#define EKEYLT "</keylen>"
#define EKEYH "<key>"
#define EKEYT "</key>"
#define IVH "<iv>"
#define IVT "</iv>"
/* read a steam of raw hex data into a buffer, we allocate the buffer, and update len
to reflect the ammount of data read in
*/
unsigned char * read_rawhex(int in, int *len)
{
unsigned char c;
int i,j;
unsigned char *buf;
unsigned char hh = 0;
*len = 0;
/* Determine how much data to read */
i = lseek(in,0,SEEK_END);
lseek(in,0,SEEK_SET);
buf = (unsigned char *)malloc(i);
if(buf != NULL) {
for(j = 0; (j < i) && (read(in,&c,1) == 1) ; j++) {
if ( !isxdigit(c) ) break;
if( (j&1) == 0 ) { /* Even numbered == high nybble */
hh = (unsigned char)x2bin(c);
} else {
buf[(*len)] = hh << 4 | (unsigned char)x2bin(c);
(*len)++;
}
}
}
return buf;
}
/* write a steam of raw hex data from a buffer to a file
status is pretty meaningless, returns number of bytes sucessfully written
*/
int write_rawhex(int out,unsigned char *buffer, int len)
{
int i;
unsigned char cb[2];
for(i = 0; i < len; i++) {
bin2x(buffer[i],cb);
if( write(out,cb,2) != 2) break;
}
return i;
}
int x2bin(char c) {
int i = 0;
c = tolower(c);
if( c >= 'a' && c <= 'f') {
i = c - 'a' + 10;
} else if (c >= '0' && c <= '9' ) {
i = c - '0';
}
return i;
}
static unsigned char bin2xn(unsigned char in)
{
if ( in <= 9 ) in += '0';
else in += ('a' - 10);
return in;
}
void bin2x(unsigned char in,unsigned char out[2]) {
unsigned char hi,lo;
hi = (in >> 4) & 0x0f;
lo = in & 0x0f;
out[0] = bin2xn(hi);
out[1] = bin2xn(lo);
}
/* Convert a stream of bytes to hex
We do 0 terminate the buffer
return value is length of string (not including the 0 terminator)
*/
int Bin2HexBuffer(char *in,int inlen,char **out)
{
int i = 0;
unsigned char *ptr;
if(out != NULL && *out == NULL) {
*out = (char *)malloc(inlen*2 +1);
}
if( out != NULL && *out != NULL) {
ptr = (unsigned char *)*out;
for(i = 0; i < inlen; i ++,ptr += 2) {
bin2x(in[i],ptr);
}
*ptr = '\0';
}
return i*2;
}
/* Convert a stream of hex data to binary
We '\0' terminate the returned buffer IFF we allocate it
return value is number of bytes returned
*/
int Hex2BinBuffer(char *in,int inlen,char **out)
{
int i =0,j = 0;
int alloc = 0;
unsigned char c,hh = 0;
char *ptr;
if(out != NULL && *out == NULL) {
*out = (char *)malloc(inlen/2+1);
alloc = 1;
}
if( out != NULL && *out != NULL) {
ptr = *out;
for(i = j = 0; i < inlen; i ++) {
c = in[i];
if ( !isxdigit(c) ) break;
if( !(i&1) ) { /* Even numbered == high nybble */
hh = (unsigned char)x2bin(c);
} else {
ptr[j] = hh << 4 | (unsigned char)x2bin(c);
j++;
}
}
if(alloc) ptr[j] = '\0';
}
return j;
}
/* Routines to write and read symetric key data */
void write_iv(int dumpFile,int ekeylen,char *ekey,char *iv)
{
char outBuf[IVBUFLEN];
char *p1;
sprintf(outBuf,"%s%d%s\n%s",EKEYLH,ekeylen,EKEYLT,EKEYH);
write(dumpFile,outBuf,strlen(outBuf));
p1 = outBuf;
Bin2HexBuffer(ekey,(ekeylen),&p1);
write(dumpFile,outBuf,ekeylen*2);
sprintf(outBuf,"%s\n%s",EKEYT,IVH);
write(dumpFile,outBuf,strlen(outBuf));
p1 = outBuf;
Bin2HexBuffer(iv,EVP_MAX_IV_LENGTH,&p1);
write(dumpFile,outBuf,EVP_MAX_IV_LENGTH*2);
sprintf(outBuf,"%s\n",IVT);
write(dumpFile,outBuf,strlen(outBuf));
}
void read_iv(int dumpFile,int *keylen,char *ekey,char *iv)
{
char buf[IVBUFLEN];
char *ptr,*ptr1;
char *p1;
read(dumpFile,buf,IVBUFLEN); /* read WILL be short */
ptr = strstr(buf,EKEYH);
ptr1 = strstr(buf,EKEYT);
if(ptr && ptr1) {
ptr += strlen(EKEYH);
p1 = ekey;
Hex2BinBuffer(ptr,ptr1-ptr,&p1);
}
ptr = strstr(buf,IVH);
ptr1 = strstr(buf,IVT);
if(ptr && ptr1) {
ptr += strlen(IVH);
p1 = iv;
Hex2BinBuffer(ptr,ptr1-ptr,&p1);
}
ptr = strstr(buf,EKEYLH);
ptr1 = strstr(buf,EKEYLT);
if(ptr && ptr1) {
ptr += strlen(EKEYLH);
*keylen = atoi(ptr);
}
}
/*! @brief return a ^ b on the numbers represented in hexadecimal in a and b.
if result is NULL, we allocate storage.
*/
unsigned char *xor_hex(unsigned char *result,unsigned char *a, unsigned char *b)
{
unsigned char *rv = NULL;
unsigned char *ptr = NULL;
int al,bl,l;
if(result == NULL) {
al = strlen((char *)a);
bl = strlen((char *)b);
l = ((al > bl) ? al : bl) + 1;
rv = (unsigned char *)calloc(1,l);
} else {
rv = result;
}
ptr = rv;
while(*a && * b) {
*ptr = bin2xn(x2bin(*a) ^ x2bin(*b));
a++;
b++;
ptr++;
}
while(*a) {
*ptr = *a;
a++;
ptr++;
}
*ptr = '\0';
return rv;
}
/*! @brief return a & b on the numbers represented in hexadecimal in a and b.
if result is NULL, we allocate storage.
*/
unsigned char *and_hex(unsigned char *result,unsigned char *a,unsigned char *b)
{
unsigned char *rv = NULL;
unsigned char *ptr = NULL;
int al,bl,l;
if(result == NULL) {
al = strlen((char *)a);
bl = strlen((char *)b);
l = ((al > bl) ? al : bl) + 1;
rv = (unsigned char *)calloc(1,l);
} else {
rv = result;
}
ptr = rv;
while(*a && * b) {
*ptr = bin2xn(x2bin(*a) & x2bin(*b));
a++;
b++;
ptr++;
}
while(*a) {
*ptr = *a;
a++;
ptr++;
}
*ptr = '\0';
return rv;
}
/*! @brief return a | b on the numbers represented in hexadecimal in a and b.
if result is NULL, we allocate storage.
*/
unsigned char *or_hex(unsigned char *result,unsigned char *a,unsigned char *b)
{
unsigned char *rv = NULL;
unsigned char *ptr = NULL;
int al,bl,l;
if(result == NULL) {
al = strlen((char *)a);
bl = strlen((char *)b);
l = ((al > bl) ? al : bl) + 1;
rv = (unsigned char *)calloc(1,l);
} else {
rv = result;
}
ptr = rv;
while(*a && * b) {
*ptr = bin2xn(x2bin(*a) | x2bin(*b));
a++;
b++;
ptr++;
}
while(*a) {
*ptr = *a;
a++;
ptr++;
}
*ptr = '\0';
return rv;
}
/* Higher level Hex conversion routines */
/* convert a binary string to a hexstring */
HEXSTRING binstr_to_hexstr(BINSTRING b)
{
unsigned char *tmp;
HEXSTRING x;
int l;
l = getbinlen(b);
tmp = setbuffer_from_binstr(NULL,b);
x = get_hexstr_frombuffer(tmp,l);
free(tmp);
return x;
}
/* Reverse of above, convert a binary buffer to a readable string */
BINSTRING get_binstr_frombuffer(unsigned char *buf,int len)
{
char *rv = NULL;
int i = 0,k = 0;
unsigned char v = 0;
len *= 8;
rv = (char *)calloc(len+1,1); /* enough space for the output string */
for(i = 0; i < len; i++) {
v = buf[i/8]; /* get byte from input */
k = v & ( 1 << (7-(i&7)) );
rv[i] = k ? '1':'0';
}
return rv;
}
/*
Return the equivalent binary buffer length of a hex encoded string
Doesn't validate that the string is hex
Makes sure the buffer is "large enough" i.e. allows "half-bytes"
*/
int getblen(HEXSTRING data)
{
return data ? ( (strlen(data)+1)/2): 0;
}
/*
Create and populate a buffer from a hexadecimal string
buffer can be pre-existing (and long enough !!!)
or NULL, in which case it's allocated
*/
unsigned char * setbuffer_from_hexstr(unsigned char *b,HEXSTRING s)
{
int i,j,len;
if(s) {
len = strlen(s);
if(b == NULL) {
b = (unsigned char *)malloc((len+1)/2);
}
for(i = 0,j = 0; i< len; i+=2,j++) {
b[j] = x2bin(s[i]); /* High nybble */
if( i < len) { /* If there WAS a low nybble .... */
b[j] = (b[j] << 4 ) | x2bin(s[i+1]);
}
}
}
return b;
}
/*
Given a binary buffer and length, allocate and return the buffer
converted to a hex string
*/
HEXSTRING get_hexstr_frombuffer(unsigned char *b,int len)
{
HEXSTRING rv;
int j,i;
rv = (HEXSTRING)calloc(1,(len*2)+1);
for(j = 0,i = 0; j< len; j++,i+=2) {
bin2x(b[j],(unsigned char *)&rv[i]);
}
return rv;
}
/* Binary string to buffer routines */
unsigned char * setbuffer_from_binstr(unsigned char *b,BINSTRING s)
{
int i,j,len;
if(s) {
len = strlen(s);
if(b == NULL) {
b = (unsigned char *)malloc(getbinlen(s));
}
/* i indexes into the input string, j into the binary buffer */
for(i = 0,j = -1; i< len; i++) {
if( !(i & 7) ) {
j++;
b[j] = 0;
}
if( s[i] != '0' ) {
b[j] = (b[j] | (1 << (7-(i&7))));
}
}
}
return b;
}
/*
Return the equivalent binary buffer length of a binary encoded string
Doesn't validate that the string is binary, i.e. only "0" and "1"
Makes sure the buffer is "large enough" i.e. allows "part-bytes"
*/
int getbinlen(BINSTRING data)
{
return ((strlen(data)+7)/8);
}
@@ -0,0 +1,90 @@
#if !defined(DEMO_CODE)
/*****************************************************************************
// IBM Confidential
// OCO Source Materials
// ICC
// (C) Copyright IBM Corp. 2003,2007
// The source code for this program is not published or otherwise
// divested of its trade secrets, irrespective of what has been
// deposited with the U.S. Copyright Office.
//
// File, Component, Release:
//
// icc_test/hex_utils.h, ICC_TEST, icc_8.0, icc8.0_070119
//
// Version: 1.5
//
// Date and Time File was last checked in: 07/06/06 18:34:08
// Date and Time File was extracted/checked out: 07/08/19 20:01:27
//
// Description: Common utilities for hexadecimal conversion.
//
// Authors Defect (D) or Feature (F) and Number
// ------- ------------------------------------
// PTW D39582 Add copyright notices
// PTW D39650 Add logical operators on hex strings
// PTW D39919 Refactor hex manipulation routines
//
*******************************************************************************/
#endif
#if !defined(HEX_UTILS_H)
#define HEX_UTILS_H
#if !defined(EVP_MAX_IV_LENGTH)
#define EVP_MAX_IV_LENGTH 16
#endif
#if defined(__OS2__)
#include <io.h>
#endif
#ifdef __cplusplus
extern "C" {
#endif
unsigned char * read_rawhex(int in, int *len); /* in is an fd */
int write_rawhex(int out,unsigned char *buffer, int len); /* out is an fd */
int x2bin(char c);
void bin2x(unsigned char in,unsigned char out[2]);
int Bin2HexBuffer(char *in, int inlen, char **out);
int Hex2BinBuffer(char *in, int inlen, char **out);
void write_iv(int dumpFile,int ekeylen,char *ekey,char *iv);
void read_iv(int dumpFile,int *keylen,char *ekey,char *iv);
/*! @brief return a ^ b on the numbers represented in hexadecimal in a and b.
if result is NULL, we allocate storage.
*/
unsigned char *xor_hex(unsigned char *result,unsigned char *a, unsigned char *b);
/*! @brief return a & b on the numbers represented in hexadecimal in a and b.
if result is NULL, we allocate storage.
*/
unsigned char *and_hex(unsigned char *result,unsigned char *a,unsigned char *b);
/*! @brief return a | b on the numbers represented in hexadecimal in a and b.
if result is NULL, we allocate storage.
*/
unsigned char *or_hex(unsigned char *result,unsigned char *a,unsigned char *b);
/* Higher level hex manipulation routines */
/* Simple hack to get something type-readable */
#define HEXSTRING char *
#define BINSTRING char *
HEXSTRING binstr_to_hexstr(BINSTRING b);
BINSTRING get_binstr_frombuffer(unsigned char *buf,int len);
int getblen(HEXSTRING data);
int getbinlen(BINSTRING data);
HEXSTRING get_hexstr_frombuffer(unsigned char *b,int len);
unsigned char * setbuffer_from_hexstr(unsigned char *b,HEXSTRING s);
unsigned char * setbuffer_from_binstr(unsigned char *b,BINSTRING s);
#ifdef __cplusplus
}
#endif
#endif
@@ -0,0 +1,661 @@
.file "vpaes-x86.s"
.text
.align 64
.L_vpaes_consts:
.long 218628480,235210255,168496130,67568393
.long 252381056,17041926,33884169,51187212
.long 252645135,252645135,252645135,252645135
.long 1512730624,3266504856,1377990664,3401244816
.long 830229760,1275146365,2969422977,3447763452
.long 3411033600,2979783055,338359620,2782886510
.long 4209124096,907596821,221174255,1006095553
.long 191964160,3799684038,3164090317,1589111125
.long 182528256,1777043520,2877432650,3265356744
.long 1874708224,3503451415,3305285752,363511674
.long 1606117888,3487855781,1093350906,2384367825
.long 197121,67569157,134941193,202313229
.long 67569157,134941193,202313229,197121
.long 134941193,202313229,197121,67569157
.long 202313229,197121,67569157,134941193
.long 33619971,100992007,168364043,235736079
.long 235736079,33619971,100992007,168364043
.long 168364043,235736079,33619971,100992007
.long 100992007,168364043,235736079,33619971
.long 50462976,117835012,185207048,252579084
.long 252314880,51251460,117574920,184942860
.long 184682752,252054788,50987272,118359308
.long 118099200,185467140,251790600,50727180
.long 2946363062,528716217,1300004225,1881839624
.long 1532713819,1532713819,1532713819,1532713819
.long 3602276352,4288629033,3737020424,4153884961
.long 1354558464,32357713,2958822624,3775749553
.long 1201988352,132424512,1572796698,503232858
.long 2213177600,1597421020,4103937655,675398315
.long 2749646592,4273543773,1511898873,121693092
.long 3040248576,1103263732,2871565598,1608280554
.long 2236667136,2588920351,482954393,64377734
.long 3069987328,291237287,2117370568,3650299247
.long 533321216,3573750986,2572112006,1401264716
.long 1339849704,2721158661,548607111,3445553514
.long 2128193280,3054596040,2183486460,1257083700
.long 655635200,1165381986,3923443150,2344132524
.long 190078720,256924420,290342170,357187870
.long 1610966272,2263057382,4103205268,309794674
.long 2592527872,2233205587,1335446729,3402964816
.long 3973531904,3225098121,3002836325,1918774430
.long 3870401024,2102906079,2284471353,4117666579
.long 617007872,1021508343,366931923,691083277
.long 2528395776,3491914898,2968704004,1613121270
.long 3445188352,3247741094,844474987,4093578302
.long 651481088,1190302358,1689581232,574775300
.long 4289380608,206939853,2555985458,2489840491
.long 2130264064,327674451,3566485037,3349835193
.long 2470714624,316102159,3636825756,3393945945
.byte 86,101,99,116,111,114,32,80,101,114,109,117,116,97,116,105
.byte 111,110,32,65,69,83,32,102,111,114,32,120,56,54,47,83
.byte 83,83,69,51,44,32,77,105,107,101,32,72,97,109,98,117
.byte 114,103,32,40,83,116,97,110,102,111,114,100,32,85,110,105
.byte 118,101,114,115,105,116,121,41,0
.align 64
.type _vpaes_preheat,@function
.align 16
_vpaes_preheat:
addl (%esp),%ebp
movdqa -48(%ebp),%xmm7
movdqa -16(%ebp),%xmm6
ret
.size _vpaes_preheat,.-_vpaes_preheat
.type _vpaes_encrypt_core,@function
.align 16
_vpaes_encrypt_core:
movl $16,%ecx
movl 240(%edx),%eax
movdqa %xmm6,%xmm1
movdqa (%ebp),%xmm2
pandn %xmm0,%xmm1
pand %xmm6,%xmm0
movdqu (%edx),%xmm5
.byte 102,15,56,0,208
movdqa 16(%ebp),%xmm0
pxor %xmm5,%xmm2
psrld $4,%xmm1
addl $16,%edx
.byte 102,15,56,0,193
leal 192(%ebp),%ebx
pxor %xmm2,%xmm0
jmp .L000enc_entry
.align 16
.L001enc_loop:
movdqa 32(%ebp),%xmm4
movdqa 48(%ebp),%xmm0
.byte 102,15,56,0,226
.byte 102,15,56,0,195
pxor %xmm5,%xmm4
movdqa 64(%ebp),%xmm5
pxor %xmm4,%xmm0
movdqa -64(%ebx,%ecx,1),%xmm1
.byte 102,15,56,0,234
movdqa 80(%ebp),%xmm2
movdqa (%ebx,%ecx,1),%xmm4
.byte 102,15,56,0,211
movdqa %xmm0,%xmm3
pxor %xmm5,%xmm2
.byte 102,15,56,0,193
addl $16,%edx
pxor %xmm2,%xmm0
.byte 102,15,56,0,220
addl $16,%ecx
pxor %xmm0,%xmm3
.byte 102,15,56,0,193
andl $48,%ecx
subl $1,%eax
pxor %xmm3,%xmm0
.L000enc_entry:
movdqa %xmm6,%xmm1
movdqa -32(%ebp),%xmm5
pandn %xmm0,%xmm1
psrld $4,%xmm1
pand %xmm6,%xmm0
.byte 102,15,56,0,232
movdqa %xmm7,%xmm3
pxor %xmm1,%xmm0
.byte 102,15,56,0,217
movdqa %xmm7,%xmm4
pxor %xmm5,%xmm3
.byte 102,15,56,0,224
movdqa %xmm7,%xmm2
pxor %xmm5,%xmm4
.byte 102,15,56,0,211
movdqa %xmm7,%xmm3
pxor %xmm0,%xmm2
.byte 102,15,56,0,220
movdqu (%edx),%xmm5
pxor %xmm1,%xmm3
jnz .L001enc_loop
movdqa 96(%ebp),%xmm4
movdqa 112(%ebp),%xmm0
.byte 102,15,56,0,226
pxor %xmm5,%xmm4
.byte 102,15,56,0,195
movdqa 64(%ebx,%ecx,1),%xmm1
pxor %xmm4,%xmm0
.byte 102,15,56,0,193
ret
.size _vpaes_encrypt_core,.-_vpaes_encrypt_core
.type _vpaes_decrypt_core,@function
.align 16
_vpaes_decrypt_core:
leal 608(%ebp),%ebx
movl 240(%edx),%eax
movdqa %xmm6,%xmm1
movdqa -64(%ebx),%xmm2
pandn %xmm0,%xmm1
movl %eax,%ecx
psrld $4,%xmm1
movdqu (%edx),%xmm5
shll $4,%ecx
pand %xmm6,%xmm0
.byte 102,15,56,0,208
movdqa -48(%ebx),%xmm0
xorl $48,%ecx
.byte 102,15,56,0,193
andl $48,%ecx
pxor %xmm5,%xmm2
movdqa 176(%ebp),%xmm5
pxor %xmm2,%xmm0
addl $16,%edx
leal -352(%ebx,%ecx,1),%ecx
jmp .L002dec_entry
.align 16
.L003dec_loop:
movdqa -32(%ebx),%xmm4
movdqa -16(%ebx),%xmm1
.byte 102,15,56,0,226
.byte 102,15,56,0,203
pxor %xmm4,%xmm0
movdqa (%ebx),%xmm4
pxor %xmm1,%xmm0
movdqa 16(%ebx),%xmm1
.byte 102,15,56,0,226
.byte 102,15,56,0,197
.byte 102,15,56,0,203
pxor %xmm4,%xmm0
movdqa 32(%ebx),%xmm4
pxor %xmm1,%xmm0
movdqa 48(%ebx),%xmm1
.byte 102,15,56,0,226
.byte 102,15,56,0,197
.byte 102,15,56,0,203
pxor %xmm4,%xmm0
movdqa 64(%ebx),%xmm4
pxor %xmm1,%xmm0
movdqa 80(%ebx),%xmm1
.byte 102,15,56,0,226
.byte 102,15,56,0,197
.byte 102,15,56,0,203
pxor %xmm4,%xmm0
addl $16,%edx
.byte 102,15,58,15,237,12
pxor %xmm1,%xmm0
subl $1,%eax
.L002dec_entry:
movdqa %xmm6,%xmm1
movdqa -32(%ebp),%xmm2
pandn %xmm0,%xmm1
pand %xmm6,%xmm0
psrld $4,%xmm1
.byte 102,15,56,0,208
movdqa %xmm7,%xmm3
pxor %xmm1,%xmm0
.byte 102,15,56,0,217
movdqa %xmm7,%xmm4
pxor %xmm2,%xmm3
.byte 102,15,56,0,224
pxor %xmm2,%xmm4
movdqa %xmm7,%xmm2
.byte 102,15,56,0,211
movdqa %xmm7,%xmm3
pxor %xmm0,%xmm2
.byte 102,15,56,0,220
movdqu (%edx),%xmm0
pxor %xmm1,%xmm3
jnz .L003dec_loop
movdqa 96(%ebx),%xmm4
.byte 102,15,56,0,226
pxor %xmm0,%xmm4
movdqa 112(%ebx),%xmm0
movdqa (%ecx),%xmm2
.byte 102,15,56,0,195
pxor %xmm4,%xmm0
.byte 102,15,56,0,194
ret
.size _vpaes_decrypt_core,.-_vpaes_decrypt_core
.type _vpaes_schedule_core,@function
.align 16
_vpaes_schedule_core:
addl (%esp),%ebp
movdqu (%esi),%xmm0
movdqa 320(%ebp),%xmm2
movdqa %xmm0,%xmm3
leal (%ebp),%ebx
movdqa %xmm2,4(%esp)
call _vpaes_schedule_transform
movdqa %xmm0,%xmm7
testl %edi,%edi
jnz .L004schedule_am_decrypting
movdqu %xmm0,(%edx)
jmp .L005schedule_go
.L004schedule_am_decrypting:
movdqa 256(%ebp,%ecx,1),%xmm1
.byte 102,15,56,0,217
movdqu %xmm3,(%edx)
xorl $48,%ecx
.L005schedule_go:
cmpl $192,%eax
ja .L006schedule_256
je .L007schedule_192
.L008schedule_128:
movl $10,%eax
.L009loop_schedule_128:
call _vpaes_schedule_round
decl %eax
jz .L010schedule_mangle_last
call _vpaes_schedule_mangle
jmp .L009loop_schedule_128
.align 16
.L007schedule_192:
movdqu 8(%esi),%xmm0
call _vpaes_schedule_transform
movdqa %xmm0,%xmm6
pxor %xmm4,%xmm4
movhlps %xmm4,%xmm6
movl $4,%eax
.L011loop_schedule_192:
call _vpaes_schedule_round
.byte 102,15,58,15,198,8
call _vpaes_schedule_mangle
call _vpaes_schedule_192_smear
call _vpaes_schedule_mangle
call _vpaes_schedule_round
decl %eax
jz .L010schedule_mangle_last
call _vpaes_schedule_mangle
call _vpaes_schedule_192_smear
jmp .L011loop_schedule_192
.align 16
.L006schedule_256:
movdqu 16(%esi),%xmm0
call _vpaes_schedule_transform
movl $7,%eax
.L012loop_schedule_256:
call _vpaes_schedule_mangle
movdqa %xmm0,%xmm6
call _vpaes_schedule_round
decl %eax
jz .L010schedule_mangle_last
call _vpaes_schedule_mangle
pshufd $255,%xmm0,%xmm0
movdqa %xmm7,20(%esp)
movdqa %xmm6,%xmm7
call .L_vpaes_schedule_low_round
movdqa 20(%esp),%xmm7
jmp .L012loop_schedule_256
.align 16
.L010schedule_mangle_last:
leal 384(%ebp),%ebx
testl %edi,%edi
jnz .L013schedule_mangle_last_dec
movdqa 256(%ebp,%ecx,1),%xmm1
.byte 102,15,56,0,193
leal 352(%ebp),%ebx
addl $32,%edx
.L013schedule_mangle_last_dec:
addl $-16,%edx
pxor 336(%ebp),%xmm0
call _vpaes_schedule_transform
movdqu %xmm0,(%edx)
pxor %xmm0,%xmm0
pxor %xmm1,%xmm1
pxor %xmm2,%xmm2
pxor %xmm3,%xmm3
pxor %xmm4,%xmm4
pxor %xmm5,%xmm5
pxor %xmm6,%xmm6
pxor %xmm7,%xmm7
ret
.size _vpaes_schedule_core,.-_vpaes_schedule_core
.type _vpaes_schedule_192_smear,@function
.align 16
_vpaes_schedule_192_smear:
pshufd $128,%xmm6,%xmm1
pshufd $254,%xmm7,%xmm0
pxor %xmm1,%xmm6
pxor %xmm1,%xmm1
pxor %xmm0,%xmm6
movdqa %xmm6,%xmm0
movhlps %xmm1,%xmm6
ret
.size _vpaes_schedule_192_smear,.-_vpaes_schedule_192_smear
.type _vpaes_schedule_round,@function
.align 16
_vpaes_schedule_round:
movdqa 8(%esp),%xmm2
pxor %xmm1,%xmm1
.byte 102,15,58,15,202,15
.byte 102,15,58,15,210,15
pxor %xmm1,%xmm7
pshufd $255,%xmm0,%xmm0
.byte 102,15,58,15,192,1
movdqa %xmm2,8(%esp)
.L_vpaes_schedule_low_round:
movdqa %xmm7,%xmm1
pslldq $4,%xmm7
pxor %xmm1,%xmm7
movdqa %xmm7,%xmm1
pslldq $8,%xmm7
pxor %xmm1,%xmm7
pxor 336(%ebp),%xmm7
movdqa -16(%ebp),%xmm4
movdqa -48(%ebp),%xmm5
movdqa %xmm4,%xmm1
pandn %xmm0,%xmm1
psrld $4,%xmm1
pand %xmm4,%xmm0
movdqa -32(%ebp),%xmm2
.byte 102,15,56,0,208
pxor %xmm1,%xmm0
movdqa %xmm5,%xmm3
.byte 102,15,56,0,217
pxor %xmm2,%xmm3
movdqa %xmm5,%xmm4
.byte 102,15,56,0,224
pxor %xmm2,%xmm4
movdqa %xmm5,%xmm2
.byte 102,15,56,0,211
pxor %xmm0,%xmm2
movdqa %xmm5,%xmm3
.byte 102,15,56,0,220
pxor %xmm1,%xmm3
movdqa 32(%ebp),%xmm4
.byte 102,15,56,0,226
movdqa 48(%ebp),%xmm0
.byte 102,15,56,0,195
pxor %xmm4,%xmm0
pxor %xmm7,%xmm0
movdqa %xmm0,%xmm7
ret
.size _vpaes_schedule_round,.-_vpaes_schedule_round
.type _vpaes_schedule_transform,@function
.align 16
_vpaes_schedule_transform:
movdqa -16(%ebp),%xmm2
movdqa %xmm2,%xmm1
pandn %xmm0,%xmm1
psrld $4,%xmm1
pand %xmm2,%xmm0
movdqa (%ebx),%xmm2
.byte 102,15,56,0,208
movdqa 16(%ebx),%xmm0
.byte 102,15,56,0,193
pxor %xmm2,%xmm0
ret
.size _vpaes_schedule_transform,.-_vpaes_schedule_transform
.type _vpaes_schedule_mangle,@function
.align 16
_vpaes_schedule_mangle:
movdqa %xmm0,%xmm4
movdqa 128(%ebp),%xmm5
testl %edi,%edi
jnz .L014schedule_mangle_dec
addl $16,%edx
pxor 336(%ebp),%xmm4
.byte 102,15,56,0,229
movdqa %xmm4,%xmm3
.byte 102,15,56,0,229
pxor %xmm4,%xmm3
.byte 102,15,56,0,229
pxor %xmm4,%xmm3
jmp .L015schedule_mangle_both
.align 16
.L014schedule_mangle_dec:
movdqa -16(%ebp),%xmm2
leal 416(%ebp),%esi
movdqa %xmm2,%xmm1
pandn %xmm4,%xmm1
psrld $4,%xmm1
pand %xmm2,%xmm4
movdqa (%esi),%xmm2
.byte 102,15,56,0,212
movdqa 16(%esi),%xmm3
.byte 102,15,56,0,217
pxor %xmm2,%xmm3
.byte 102,15,56,0,221
movdqa 32(%esi),%xmm2
.byte 102,15,56,0,212
pxor %xmm3,%xmm2
movdqa 48(%esi),%xmm3
.byte 102,15,56,0,217
pxor %xmm2,%xmm3
.byte 102,15,56,0,221
movdqa 64(%esi),%xmm2
.byte 102,15,56,0,212
pxor %xmm3,%xmm2
movdqa 80(%esi),%xmm3
.byte 102,15,56,0,217
pxor %xmm2,%xmm3
.byte 102,15,56,0,221
movdqa 96(%esi),%xmm2
.byte 102,15,56,0,212
pxor %xmm3,%xmm2
movdqa 112(%esi),%xmm3
.byte 102,15,56,0,217
pxor %xmm2,%xmm3
addl $-16,%edx
.L015schedule_mangle_both:
movdqa 256(%ebp,%ecx,1),%xmm1
.byte 102,15,56,0,217
addl $-16,%ecx
andl $48,%ecx
movdqu %xmm3,(%edx)
ret
.size _vpaes_schedule_mangle,.-_vpaes_schedule_mangle
.globl vpaes_set_encrypt_key
.type vpaes_set_encrypt_key,@function
.align 16
vpaes_set_encrypt_key:
.L_vpaes_set_encrypt_key_begin:
pushl %ebp
pushl %ebx
pushl %esi
pushl %edi
movl 20(%esp),%esi
leal -56(%esp),%ebx
movl 24(%esp),%eax
andl $-16,%ebx
movl 28(%esp),%edx
xchgl %esp,%ebx
movl %ebx,48(%esp)
movl %eax,%ebx
shrl $5,%ebx
addl $5,%ebx
movl %ebx,240(%edx)
movl $48,%ecx
movl $0,%edi
leal .L_vpaes_consts+0x30-.L016pic_point,%ebp
call _vpaes_schedule_core
.L016pic_point:
movl 48(%esp),%esp
xorl %eax,%eax
popl %edi
popl %esi
popl %ebx
popl %ebp
ret
.size vpaes_set_encrypt_key,.-.L_vpaes_set_encrypt_key_begin
.globl vpaes_set_decrypt_key
.type vpaes_set_decrypt_key,@function
.align 16
vpaes_set_decrypt_key:
.L_vpaes_set_decrypt_key_begin:
pushl %ebp
pushl %ebx
pushl %esi
pushl %edi
movl 20(%esp),%esi
leal -56(%esp),%ebx
movl 24(%esp),%eax
andl $-16,%ebx
movl 28(%esp),%edx
xchgl %esp,%ebx
movl %ebx,48(%esp)
movl %eax,%ebx
shrl $5,%ebx
addl $5,%ebx
movl %ebx,240(%edx)
shll $4,%ebx
leal 16(%edx,%ebx,1),%edx
movl $1,%edi
movl %eax,%ecx
shrl $1,%ecx
andl $32,%ecx
xorl $32,%ecx
leal .L_vpaes_consts+0x30-.L017pic_point,%ebp
call _vpaes_schedule_core
.L017pic_point:
movl 48(%esp),%esp
xorl %eax,%eax
popl %edi
popl %esi
popl %ebx
popl %ebp
ret
.size vpaes_set_decrypt_key,.-.L_vpaes_set_decrypt_key_begin
.globl vpaes_encrypt
.type vpaes_encrypt,@function
.align 16
vpaes_encrypt:
.L_vpaes_encrypt_begin:
pushl %ebp
pushl %ebx
pushl %esi
pushl %edi
leal .L_vpaes_consts+0x30-.L018pic_point,%ebp
call _vpaes_preheat
.L018pic_point:
movl 20(%esp),%esi
leal -56(%esp),%ebx
movl 24(%esp),%edi
andl $-16,%ebx
movl 28(%esp),%edx
xchgl %esp,%ebx
movl %ebx,48(%esp)
movdqu (%esi),%xmm0
call _vpaes_encrypt_core
movdqu %xmm0,(%edi)
movl 48(%esp),%esp
popl %edi
popl %esi
popl %ebx
popl %ebp
ret
.size vpaes_encrypt,.-.L_vpaes_encrypt_begin
.globl vpaes_decrypt
.type vpaes_decrypt,@function
.align 16
vpaes_decrypt:
.L_vpaes_decrypt_begin:
pushl %ebp
pushl %ebx
pushl %esi
pushl %edi
leal .L_vpaes_consts+0x30-.L019pic_point,%ebp
call _vpaes_preheat
.L019pic_point:
movl 20(%esp),%esi
leal -56(%esp),%ebx
movl 24(%esp),%edi
andl $-16,%ebx
movl 28(%esp),%edx
xchgl %esp,%ebx
movl %ebx,48(%esp)
movdqu (%esi),%xmm0
call _vpaes_decrypt_core
movdqu %xmm0,(%edi)
movl 48(%esp),%esp
popl %edi
popl %esi
popl %ebx
popl %ebp
ret
.size vpaes_decrypt,.-.L_vpaes_decrypt_begin
.globl vpaes_cbc_encrypt
.type vpaes_cbc_encrypt,@function
.align 16
vpaes_cbc_encrypt:
.L_vpaes_cbc_encrypt_begin:
pushl %ebp
pushl %ebx
pushl %esi
pushl %edi
movl 20(%esp),%esi
movl 24(%esp),%edi
movl 28(%esp),%eax
movl 32(%esp),%edx
subl $16,%eax
jc .L020cbc_abort
leal -56(%esp),%ebx
movl 36(%esp),%ebp
andl $-16,%ebx
movl 40(%esp),%ecx
xchgl %esp,%ebx
movdqu (%ebp),%xmm1
subl %esi,%edi
movl %ebx,48(%esp)
movl %edi,(%esp)
movl %edx,4(%esp)
movl %ebp,8(%esp)
movl %eax,%edi
leal .L_vpaes_consts+0x30-.L021pic_point,%ebp
call _vpaes_preheat
.L021pic_point:
cmpl $0,%ecx
je .L022cbc_dec_loop
jmp .L023cbc_enc_loop
.align 16
.L023cbc_enc_loop:
movdqu (%esi),%xmm0
pxor %xmm1,%xmm0
call _vpaes_encrypt_core
movl (%esp),%ebx
movl 4(%esp),%edx
movdqa %xmm0,%xmm1
movdqu %xmm0,(%ebx,%esi,1)
leal 16(%esi),%esi
subl $16,%edi
jnc .L023cbc_enc_loop
jmp .L024cbc_done
.align 16
.L022cbc_dec_loop:
movdqu (%esi),%xmm0
movdqa %xmm1,16(%esp)
movdqa %xmm0,32(%esp)
call _vpaes_decrypt_core
movl (%esp),%ebx
movl 4(%esp),%edx
pxor 16(%esp),%xmm0
movdqa 32(%esp),%xmm1
movdqu %xmm0,(%ebx,%esi,1)
leal 16(%esi),%esi
subl $16,%edi
jnc .L022cbc_dec_loop
.L024cbc_done:
movl 8(%esp),%ebx
movl 48(%esp),%esp
movdqu %xmm1,(%ebx)
.L020cbc_abort:
popl %edi
popl %esi
popl %ebx
popl %ebp
ret
.size vpaes_cbc_encrypt,.-.L_vpaes_cbc_encrypt_begin
@@ -0,0 +1,827 @@
.text
.type _vpaes_encrypt_core,@function
.align 16
_vpaes_encrypt_core:
movq %rdx,%r9
movq $16,%r11
movl 240(%rdx),%eax
movdqa %xmm9,%xmm1
movdqa .Lk_ipt(%rip),%xmm2
pandn %xmm0,%xmm1
movdqu (%r9),%xmm5
psrld $4,%xmm1
pand %xmm9,%xmm0
.byte 102,15,56,0,208
movdqa .Lk_ipt+16(%rip),%xmm0
.byte 102,15,56,0,193
pxor %xmm5,%xmm2
addq $16,%r9
pxor %xmm2,%xmm0
leaq .Lk_mc_backward(%rip),%r10
jmp .Lenc_entry
.align 16
.Lenc_loop:
movdqa %xmm13,%xmm4
movdqa %xmm12,%xmm0
.byte 102,15,56,0,226
.byte 102,15,56,0,195
pxor %xmm5,%xmm4
movdqa %xmm15,%xmm5
pxor %xmm4,%xmm0
movdqa -64(%r11,%r10,1),%xmm1
.byte 102,15,56,0,234
movdqa (%r11,%r10,1),%xmm4
movdqa %xmm14,%xmm2
.byte 102,15,56,0,211
movdqa %xmm0,%xmm3
pxor %xmm5,%xmm2
.byte 102,15,56,0,193
addq $16,%r9
pxor %xmm2,%xmm0
.byte 102,15,56,0,220
addq $16,%r11
pxor %xmm0,%xmm3
.byte 102,15,56,0,193
andq $0x30,%r11
subq $1,%rax
pxor %xmm3,%xmm0
.Lenc_entry:
movdqa %xmm9,%xmm1
movdqa %xmm11,%xmm5
pandn %xmm0,%xmm1
psrld $4,%xmm1
pand %xmm9,%xmm0
.byte 102,15,56,0,232
movdqa %xmm10,%xmm3
pxor %xmm1,%xmm0
.byte 102,15,56,0,217
movdqa %xmm10,%xmm4
pxor %xmm5,%xmm3
.byte 102,15,56,0,224
movdqa %xmm10,%xmm2
pxor %xmm5,%xmm4
.byte 102,15,56,0,211
movdqa %xmm10,%xmm3
pxor %xmm0,%xmm2
.byte 102,15,56,0,220
movdqu (%r9),%xmm5
pxor %xmm1,%xmm3
jnz .Lenc_loop
movdqa -96(%r10),%xmm4
movdqa -80(%r10),%xmm0
.byte 102,15,56,0,226
pxor %xmm5,%xmm4
.byte 102,15,56,0,195
movdqa 64(%r11,%r10,1),%xmm1
pxor %xmm4,%xmm0
.byte 102,15,56,0,193
.byte 0xf3,0xc3
.size _vpaes_encrypt_core,.-_vpaes_encrypt_core
.type _vpaes_decrypt_core,@function
.align 16
_vpaes_decrypt_core:
movq %rdx,%r9
movl 240(%rdx),%eax
movdqa %xmm9,%xmm1
movdqa .Lk_dipt(%rip),%xmm2
pandn %xmm0,%xmm1
movq %rax,%r11
psrld $4,%xmm1
movdqu (%r9),%xmm5
shlq $4,%r11
pand %xmm9,%xmm0
.byte 102,15,56,0,208
movdqa .Lk_dipt+16(%rip),%xmm0
xorq $0x30,%r11
leaq .Lk_dsbd(%rip),%r10
.byte 102,15,56,0,193
andq $0x30,%r11
pxor %xmm5,%xmm2
movdqa .Lk_mc_forward+48(%rip),%xmm5
pxor %xmm2,%xmm0
addq $16,%r9
addq %r10,%r11
jmp .Ldec_entry
.align 16
.Ldec_loop:
movdqa -32(%r10),%xmm4
movdqa -16(%r10),%xmm1
.byte 102,15,56,0,226
.byte 102,15,56,0,203
pxor %xmm4,%xmm0
movdqa 0(%r10),%xmm4
pxor %xmm1,%xmm0
movdqa 16(%r10),%xmm1
.byte 102,15,56,0,226
.byte 102,15,56,0,197
.byte 102,15,56,0,203
pxor %xmm4,%xmm0
movdqa 32(%r10),%xmm4
pxor %xmm1,%xmm0
movdqa 48(%r10),%xmm1
.byte 102,15,56,0,226
.byte 102,15,56,0,197
.byte 102,15,56,0,203
pxor %xmm4,%xmm0
movdqa 64(%r10),%xmm4
pxor %xmm1,%xmm0
movdqa 80(%r10),%xmm1
.byte 102,15,56,0,226
.byte 102,15,56,0,197
.byte 102,15,56,0,203
pxor %xmm4,%xmm0
addq $16,%r9
.byte 102,15,58,15,237,12
pxor %xmm1,%xmm0
subq $1,%rax
.Ldec_entry:
movdqa %xmm9,%xmm1
pandn %xmm0,%xmm1
movdqa %xmm11,%xmm2
psrld $4,%xmm1
pand %xmm9,%xmm0
.byte 102,15,56,0,208
movdqa %xmm10,%xmm3
pxor %xmm1,%xmm0
.byte 102,15,56,0,217
movdqa %xmm10,%xmm4
pxor %xmm2,%xmm3
.byte 102,15,56,0,224
pxor %xmm2,%xmm4
movdqa %xmm10,%xmm2
.byte 102,15,56,0,211
movdqa %xmm10,%xmm3
pxor %xmm0,%xmm2
.byte 102,15,56,0,220
movdqu (%r9),%xmm0
pxor %xmm1,%xmm3
jnz .Ldec_loop
movdqa 96(%r10),%xmm4
.byte 102,15,56,0,226
pxor %xmm0,%xmm4
movdqa 112(%r10),%xmm0
movdqa -352(%r11),%xmm2
.byte 102,15,56,0,195
pxor %xmm4,%xmm0
.byte 102,15,56,0,194
.byte 0xf3,0xc3
.size _vpaes_decrypt_core,.-_vpaes_decrypt_core
.type _vpaes_schedule_core,@function
.align 16
_vpaes_schedule_core:
call _vpaes_preheat
movdqa .Lk_rcon(%rip),%xmm8
movdqu (%rdi),%xmm0
movdqa %xmm0,%xmm3
leaq .Lk_ipt(%rip),%r11
call _vpaes_schedule_transform
movdqa %xmm0,%xmm7
leaq .Lk_sr(%rip),%r10
testq %rcx,%rcx
jnz .Lschedule_am_decrypting
movdqu %xmm0,(%rdx)
jmp .Lschedule_go
.Lschedule_am_decrypting:
movdqa (%r8,%r10,1),%xmm1
.byte 102,15,56,0,217
movdqu %xmm3,(%rdx)
xorq $0x30,%r8
.Lschedule_go:
cmpl $192,%esi
ja .Lschedule_256
je .Lschedule_192
.Lschedule_128:
movl $10,%esi
.Loop_schedule_128:
call _vpaes_schedule_round
decq %rsi
jz .Lschedule_mangle_last
call _vpaes_schedule_mangle
jmp .Loop_schedule_128
.align 16
.Lschedule_192:
movdqu 8(%rdi),%xmm0
call _vpaes_schedule_transform
movdqa %xmm0,%xmm6
pxor %xmm4,%xmm4
movhlps %xmm4,%xmm6
movl $4,%esi
.Loop_schedule_192:
call _vpaes_schedule_round
.byte 102,15,58,15,198,8
call _vpaes_schedule_mangle
call _vpaes_schedule_192_smear
call _vpaes_schedule_mangle
call _vpaes_schedule_round
decq %rsi
jz .Lschedule_mangle_last
call _vpaes_schedule_mangle
call _vpaes_schedule_192_smear
jmp .Loop_schedule_192
.align 16
.Lschedule_256:
movdqu 16(%rdi),%xmm0
call _vpaes_schedule_transform
movl $7,%esi
.Loop_schedule_256:
call _vpaes_schedule_mangle
movdqa %xmm0,%xmm6
call _vpaes_schedule_round
decq %rsi
jz .Lschedule_mangle_last
call _vpaes_schedule_mangle
pshufd $0xFF,%xmm0,%xmm0
movdqa %xmm7,%xmm5
movdqa %xmm6,%xmm7
call _vpaes_schedule_low_round
movdqa %xmm5,%xmm7
jmp .Loop_schedule_256
.align 16
.Lschedule_mangle_last:
leaq .Lk_deskew(%rip),%r11
testq %rcx,%rcx
jnz .Lschedule_mangle_last_dec
movdqa (%r8,%r10,1),%xmm1
.byte 102,15,56,0,193
leaq .Lk_opt(%rip),%r11
addq $32,%rdx
.Lschedule_mangle_last_dec:
addq $-16,%rdx
pxor .Lk_s63(%rip),%xmm0
call _vpaes_schedule_transform
movdqu %xmm0,(%rdx)
pxor %xmm0,%xmm0
pxor %xmm1,%xmm1
pxor %xmm2,%xmm2
pxor %xmm3,%xmm3
pxor %xmm4,%xmm4
pxor %xmm5,%xmm5
pxor %xmm6,%xmm6
pxor %xmm7,%xmm7
.byte 0xf3,0xc3
.size _vpaes_schedule_core,.-_vpaes_schedule_core
.type _vpaes_schedule_192_smear,@function
.align 16
_vpaes_schedule_192_smear:
pshufd $0x80,%xmm6,%xmm1
pshufd $0xFE,%xmm7,%xmm0
pxor %xmm1,%xmm6
pxor %xmm1,%xmm1
pxor %xmm0,%xmm6
movdqa %xmm6,%xmm0
movhlps %xmm1,%xmm6
.byte 0xf3,0xc3
.size _vpaes_schedule_192_smear,.-_vpaes_schedule_192_smear
.type _vpaes_schedule_round,@function
.align 16
_vpaes_schedule_round:
pxor %xmm1,%xmm1
.byte 102,65,15,58,15,200,15
.byte 102,69,15,58,15,192,15
pxor %xmm1,%xmm7
pshufd $0xFF,%xmm0,%xmm0
.byte 102,15,58,15,192,1
_vpaes_schedule_low_round:
movdqa %xmm7,%xmm1
pslldq $4,%xmm7
pxor %xmm1,%xmm7
movdqa %xmm7,%xmm1
pslldq $8,%xmm7
pxor %xmm1,%xmm7
pxor .Lk_s63(%rip),%xmm7
movdqa %xmm9,%xmm1
pandn %xmm0,%xmm1
psrld $4,%xmm1
pand %xmm9,%xmm0
movdqa %xmm11,%xmm2
.byte 102,15,56,0,208
pxor %xmm1,%xmm0
movdqa %xmm10,%xmm3
.byte 102,15,56,0,217
pxor %xmm2,%xmm3
movdqa %xmm10,%xmm4
.byte 102,15,56,0,224
pxor %xmm2,%xmm4
movdqa %xmm10,%xmm2
.byte 102,15,56,0,211
pxor %xmm0,%xmm2
movdqa %xmm10,%xmm3
.byte 102,15,56,0,220
pxor %xmm1,%xmm3
movdqa %xmm13,%xmm4
.byte 102,15,56,0,226
movdqa %xmm12,%xmm0
.byte 102,15,56,0,195
pxor %xmm4,%xmm0
pxor %xmm7,%xmm0
movdqa %xmm0,%xmm7
.byte 0xf3,0xc3
.size _vpaes_schedule_round,.-_vpaes_schedule_round
.type _vpaes_schedule_transform,@function
.align 16
_vpaes_schedule_transform:
movdqa %xmm9,%xmm1
pandn %xmm0,%xmm1
psrld $4,%xmm1
pand %xmm9,%xmm0
movdqa (%r11),%xmm2
.byte 102,15,56,0,208
movdqa 16(%r11),%xmm0
.byte 102,15,56,0,193
pxor %xmm2,%xmm0
.byte 0xf3,0xc3
.size _vpaes_schedule_transform,.-_vpaes_schedule_transform
.type _vpaes_schedule_mangle,@function
.align 16
_vpaes_schedule_mangle:
movdqa %xmm0,%xmm4
movdqa .Lk_mc_forward(%rip),%xmm5
testq %rcx,%rcx
jnz .Lschedule_mangle_dec
addq $16,%rdx
pxor .Lk_s63(%rip),%xmm4
.byte 102,15,56,0,229
movdqa %xmm4,%xmm3
.byte 102,15,56,0,229
pxor %xmm4,%xmm3
.byte 102,15,56,0,229
pxor %xmm4,%xmm3
jmp .Lschedule_mangle_both
.align 16
.Lschedule_mangle_dec:
leaq .Lk_dksd(%rip),%r11
movdqa %xmm9,%xmm1
pandn %xmm4,%xmm1
psrld $4,%xmm1
pand %xmm9,%xmm4
movdqa 0(%r11),%xmm2
.byte 102,15,56,0,212
movdqa 16(%r11),%xmm3
.byte 102,15,56,0,217
pxor %xmm2,%xmm3
.byte 102,15,56,0,221
movdqa 32(%r11),%xmm2
.byte 102,15,56,0,212
pxor %xmm3,%xmm2
movdqa 48(%r11),%xmm3
.byte 102,15,56,0,217
pxor %xmm2,%xmm3
.byte 102,15,56,0,221
movdqa 64(%r11),%xmm2
.byte 102,15,56,0,212
pxor %xmm3,%xmm2
movdqa 80(%r11),%xmm3
.byte 102,15,56,0,217
pxor %xmm2,%xmm3
.byte 102,15,56,0,221
movdqa 96(%r11),%xmm2
.byte 102,15,56,0,212
pxor %xmm3,%xmm2
movdqa 112(%r11),%xmm3
.byte 102,15,56,0,217
pxor %xmm2,%xmm3
addq $-16,%rdx
.Lschedule_mangle_both:
movdqa (%r8,%r10,1),%xmm1
.byte 102,15,56,0,217
addq $-16,%r8
andq $0x30,%r8
movdqu %xmm3,(%rdx)
.byte 0xf3,0xc3
.size _vpaes_schedule_mangle,.-_vpaes_schedule_mangle
.globl vpaes_set_encrypt_key
.type vpaes_set_encrypt_key,@function
.align 16
vpaes_set_encrypt_key:
movl %esi,%eax
shrl $5,%eax
addl $5,%eax
movl %eax,240(%rdx)
movl $0,%ecx
movl $0x30,%r8d
call _vpaes_schedule_core
xorl %eax,%eax
.byte 0xf3,0xc3
.size vpaes_set_encrypt_key,.-vpaes_set_encrypt_key
.globl vpaes_set_decrypt_key
.type vpaes_set_decrypt_key,@function
.align 16
vpaes_set_decrypt_key:
movl %esi,%eax
shrl $5,%eax
addl $5,%eax
movl %eax,240(%rdx)
shll $4,%eax
leaq 16(%rdx,%rax,1),%rdx
movl $1,%ecx
movl %esi,%r8d
shrl $1,%r8d
andl $32,%r8d
xorl $32,%r8d
call _vpaes_schedule_core
xorl %eax,%eax
.byte 0xf3,0xc3
.size vpaes_set_decrypt_key,.-vpaes_set_decrypt_key
.globl vpaes_encrypt
.type vpaes_encrypt,@function
.align 16
vpaes_encrypt:
movdqu (%rdi),%xmm0
call _vpaes_preheat
call _vpaes_encrypt_core
movdqu %xmm0,(%rsi)
.byte 0xf3,0xc3
.size vpaes_encrypt,.-vpaes_encrypt
.globl vpaes_decrypt
.type vpaes_decrypt,@function
.align 16
vpaes_decrypt:
movdqu (%rdi),%xmm0
call _vpaes_preheat
call _vpaes_decrypt_core
movdqu %xmm0,(%rsi)
.byte 0xf3,0xc3
.size vpaes_decrypt,.-vpaes_decrypt
.globl vpaes_cbc_encrypt
.type vpaes_cbc_encrypt,@function
.align 16
vpaes_cbc_encrypt:
xchgq %rcx,%rdx
subq $16,%rcx
jc .Lcbc_abort
movdqu (%r8),%xmm6
subq %rdi,%rsi
call _vpaes_preheat
cmpl $0,%r9d
je .Lcbc_dec_loop
jmp .Lcbc_enc_loop
.align 16
.Lcbc_enc_loop:
movdqu (%rdi),%xmm0
pxor %xmm6,%xmm0
call _vpaes_encrypt_core
movdqa %xmm0,%xmm6
movdqu %xmm0,(%rsi,%rdi,1)
leaq 16(%rdi),%rdi
subq $16,%rcx
jnc .Lcbc_enc_loop
jmp .Lcbc_done
.align 16
.Lcbc_dec_loop:
movdqu (%rdi),%xmm0
movdqa %xmm0,%xmm7
call _vpaes_decrypt_core
pxor %xmm6,%xmm0
movdqa %xmm7,%xmm6
movdqu %xmm0,(%rsi,%rdi,1)
leaq 16(%rdi),%rdi
subq $16,%rcx
jnc .Lcbc_dec_loop
.Lcbc_done:
movdqu %xmm6,(%r8)
.Lcbc_abort:
.byte 0xf3,0xc3
.size vpaes_cbc_encrypt,.-vpaes_cbc_encrypt
.type _vpaes_preheat,@function
.align 16
_vpaes_preheat:
leaq .Lk_s0F(%rip),%r10
movdqa -32(%r10),%xmm10
movdqa -16(%r10),%xmm11
movdqa 0(%r10),%xmm9
movdqa 48(%r10),%xmm13
movdqa 64(%r10),%xmm12
movdqa 80(%r10),%xmm15
movdqa 96(%r10),%xmm14
.byte 0xf3,0xc3
.size _vpaes_preheat,.-_vpaes_preheat
.type _vpaes_consts,@object
.align 64
_vpaes_consts:
.Lk_inv:
.quad 0x0E05060F0D080180, 0x040703090A0B0C02
.quad 0x01040A060F0B0780, 0x030D0E0C02050809
.Lk_s0F:
.quad 0x0F0F0F0F0F0F0F0F, 0x0F0F0F0F0F0F0F0F
.Lk_ipt:
.quad 0xC2B2E8985A2A7000, 0xCABAE09052227808
.quad 0x4C01307D317C4D00, 0xCD80B1FCB0FDCC81
.Lk_sb1:
.quad 0xB19BE18FCB503E00, 0xA5DF7A6E142AF544
.quad 0x3618D415FAE22300, 0x3BF7CCC10D2ED9EF
.Lk_sb2:
.quad 0xE27A93C60B712400, 0x5EB7E955BC982FCD
.quad 0x69EB88400AE12900, 0xC2A163C8AB82234A
.Lk_sbo:
.quad 0xD0D26D176FBDC700, 0x15AABF7AC502A878
.quad 0xCFE474A55FBB6A00, 0x8E1E90D1412B35FA
.Lk_mc_forward:
.quad 0x0407060500030201, 0x0C0F0E0D080B0A09
.quad 0x080B0A0904070605, 0x000302010C0F0E0D
.quad 0x0C0F0E0D080B0A09, 0x0407060500030201
.quad 0x000302010C0F0E0D, 0x080B0A0904070605
.Lk_mc_backward:
.quad 0x0605040702010003, 0x0E0D0C0F0A09080B
.quad 0x020100030E0D0C0F, 0x0A09080B06050407
.quad 0x0E0D0C0F0A09080B, 0x0605040702010003
.quad 0x0A09080B06050407, 0x020100030E0D0C0F
.Lk_sr:
.quad 0x0706050403020100, 0x0F0E0D0C0B0A0908
.quad 0x030E09040F0A0500, 0x0B06010C07020D08
.quad 0x0F060D040B020900, 0x070E050C030A0108
.quad 0x0B0E0104070A0D00, 0x0306090C0F020508
.Lk_rcon:
.quad 0x1F8391B9AF9DEEB6, 0x702A98084D7C7D81
.Lk_s63:
.quad 0x5B5B5B5B5B5B5B5B, 0x5B5B5B5B5B5B5B5B
.Lk_opt:
.quad 0xFF9F4929D6B66000, 0xF7974121DEBE6808
.quad 0x01EDBD5150BCEC00, 0xE10D5DB1B05C0CE0
.Lk_deskew:
.quad 0x07E4A34047A4E300, 0x1DFEB95A5DBEF91A
.quad 0x5F36B5DC83EA6900, 0x2841C2ABF49D1E77
.Lk_dksd:
.quad 0xFEB91A5DA3E44700, 0x0740E3A45A1DBEF9
.quad 0x41C277F4B5368300, 0x5FDC69EAAB289D1E
.Lk_dksb:
.quad 0x9A4FCA1F8550D500, 0x03D653861CC94C99
.quad 0x115BEDA7B6FC4A00, 0xD993256F7E3482C8
.Lk_dkse:
.quad 0xD5031CCA1FC9D600, 0x53859A4C994F5086
.quad 0xA23196054FDC7BE8, 0xCD5EF96A20B31487
.Lk_dks9:
.quad 0xB6116FC87ED9A700, 0x4AED933482255BFC
.quad 0x4576516227143300, 0x8BB89FACE9DAFDCE
.Lk_dipt:
.quad 0x0F505B040B545F00, 0x154A411E114E451A
.quad 0x86E383E660056500, 0x12771772F491F194
.Lk_dsb9:
.quad 0x851C03539A86D600, 0xCAD51F504F994CC9
.quad 0xC03B1789ECD74900, 0x725E2C9EB2FBA565
.Lk_dsbd:
.quad 0x7D57CCDFE6B1A200, 0xF56E9B13882A4439
.quad 0x3CE2FAF724C6CB00, 0x2931180D15DEEFD3
.Lk_dsbb:
.quad 0xD022649296B44200, 0x602646F6B0F2D404
.quad 0xC19498A6CD596700, 0xF3FF0C3E3255AA6B
.Lk_dsbe:
.quad 0x46F2929626D4D000, 0x2242600464B4F6B0
.quad 0x0C55A6CDFFAAC100, 0x9467F36B98593E32
.Lk_dsbo:
.quad 0x1387EA537EF94000, 0xC7AA6DB9D4943E2D
.quad 0x12D7560F93441D00, 0xCA4B8159D8C58E9C
.byte 86,101,99,116,111,114,32,80,101,114,109,117,116,97,116,105,111,110,32,65,69,83,32,102,111,114,32,120,56,54,95,54,52,47,83,83,83,69,51,44,32,77,105,107,101,32,72,97,109,98,117,114,103,32,40,83,116,97,110,102,111,114,100,32,85,110,105,118,101,114,115,105,116,121,41,0
.align 64
.size _vpaes_consts,.-_vpaes_consts
@@ -0,0 +1,81 @@
#ifndef __ARM_ARCH_H__
# define __ARM_ARCH_H__
# if !defined(__ARM_ARCH__)
# if defined(__CC_ARM)
# define __ARM_ARCH__ __TARGET_ARCH_ARM
# if defined(__BIG_ENDIAN)
# define __ARMEB__
# else
# define __ARMEL__
# endif
# elif defined(__GNUC__)
# if defined(__aarch64__)
# define __ARM_ARCH__ 8
# if __BYTE_ORDER__==__ORDER_BIG_ENDIAN__
# define __ARMEB__
# else
# define __ARMEL__
# endif
/*
* Why doesn't gcc define __ARM_ARCH__? Instead it defines
* bunch of below macros. See all_architectires[] table in
* gcc/config/arm/arm.c. On a side note it defines
* __ARMEL__/__ARMEB__ for little-/big-endian.
*/
# elif defined(__ARM_ARCH)
# define __ARM_ARCH__ __ARM_ARCH
# elif defined(__ARM_ARCH_8A__)
# define __ARM_ARCH__ 8
# elif defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) || \
defined(__ARM_ARCH_7R__)|| defined(__ARM_ARCH_7M__) || \
defined(__ARM_ARCH_7EM__)
# define __ARM_ARCH__ 7
# elif defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) || \
defined(__ARM_ARCH_6K__)|| defined(__ARM_ARCH_6M__) || \
defined(__ARM_ARCH_6Z__)|| defined(__ARM_ARCH_6ZK__) || \
defined(__ARM_ARCH_6T2__)
# define __ARM_ARCH__ 6
# elif defined(__ARM_ARCH_5__) || defined(__ARM_ARCH_5T__) || \
defined(__ARM_ARCH_5E__)|| defined(__ARM_ARCH_5TE__) || \
defined(__ARM_ARCH_5TEJ__)
# define __ARM_ARCH__ 5
# elif defined(__ARM_ARCH_4__) || defined(__ARM_ARCH_4T__)
# define __ARM_ARCH__ 4
# else
# error "unsupported ARM architecture"
# endif
# endif
# endif
# ifdef OPENSSL_FIPSCANISTER
# include <openssl/fipssyms.h>
# endif
#ifdef __DCC__
# define __ASSEMBLER__ 1
#endif /* __DCC__ */
# if !defined(__ARM_MAX_ARCH__)
# define __ARM_MAX_ARCH__ __ARM_ARCH__
# endif
# if __ARM_MAX_ARCH__<__ARM_ARCH__
# error "__ARM_MAX_ARCH__ can't be less than __ARM_ARCH__"
# elif __ARM_MAX_ARCH__!=__ARM_ARCH__
# if __ARM_ARCH__<7 && __ARM_MAX_ARCH__>=7 && defined(__ARMEB__)
# error "can't build universal big-endian binary"
# endif
# endif
# ifndef __ASSEMBLER__
extern unsigned int OPENSSL_armcap_P;
# endif
# define ARMV7_NEON (1<<0)
# define ARMV7_TICK (1<<1)
# define ARMV8_AES (1<<2)
# define ARMV8_SHA1 (1<<3)
# define ARMV8_SHA256 (1<<4)
# define ARMV8_PMULL (1<<5)
#endif
@@ -0,0 +1,167 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#if 0
#include <setjmp.h>
#endif
#include <signal.h>
#include <openssl/crypto.h>
#include "cryptlib.h"
#include "arm_arch.h"
unsigned int OPENSSL_armcap_P = 0;
#if __ARM_MAX_ARCH__<7
void OPENSSL_cpuid_setup(void)
{
}
unsigned long OPENSSL_rdtsc(void)
{
return 0;
}
#else
static sigset_t all_masked;
static sigjmp_buf ill_jmp;
static void ill_handler(int sig)
{
/*siglongjmp(ill_jmp, sig);*/
longjmp(ill_jmp, sig);
}
/*
* Following subroutines could have been inlined, but it's not all
* ARM compilers support inline assembler...
*/
void _armv7_neon_probe(void);
void _armv8_aes_probe(void);
void _armv8_sha1_probe(void);
void _armv8_sha256_probe(void);
void _armv8_pmull_probe(void);
unsigned long _armv7_tick(void);
unsigned long OPENSSL_rdtsc(void)
{
if (OPENSSL_armcap_P & ARMV7_TICK)
return _armv7_tick();
else
return 0;
}
/*
* Use a weak reference to getauxval() so we can use it if it is available but
* don't break the build if it is not.
*/
# if defined(__GNUC__) && __GNUC__>=2
void OPENSSL_cpuid_setup(void) __attribute__ ((constructor));
extern unsigned long getauxval(unsigned long type) __attribute__ ((weak));
# else
static unsigned long (*getauxval) (unsigned long) = NULL;
# endif
/*
* ARM puts the the feature bits for Crypto Extensions in AT_HWCAP2, whereas
* AArch64 used AT_HWCAP.
*/
# if defined(__arm__) || defined (__arm)
# define HWCAP 16
/* AT_HWCAP */
# define HWCAP_NEON (1 << 12)
# define HWCAP_CE 26
/* AT_HWCAP2 */
# define HWCAP_CE_AES (1 << 0)
# define HWCAP_CE_PMULL (1 << 1)
# define HWCAP_CE_SHA1 (1 << 2)
# define HWCAP_CE_SHA256 (1 << 3)
# elif defined(__aarch64__)
# define HWCAP 16
/* AT_HWCAP */
# define HWCAP_NEON (1 << 1)
# define HWCAP_CE HWCAP
# define HWCAP_CE_AES (1 << 3)
# define HWCAP_CE_PMULL (1 << 4)
# define HWCAP_CE_SHA1 (1 << 5)
# define HWCAP_CE_SHA256 (1 << 6)
# endif
void OPENSSL_cpuid_setup(void)
{
char *e;
struct sigaction ill_oact, ill_act;
sigset_t oset;
static int trigger = 0;
if (trigger)
return;
trigger = 1;
if ((e = getenv("OPENSSL_armcap"))) {
OPENSSL_armcap_P = (unsigned int)strtoul(e, NULL, 0);
return;
}
sigfillset(&all_masked);
sigdelset(&all_masked, SIGILL);
sigdelset(&all_masked, SIGTRAP);
sigdelset(&all_masked, SIGFPE);
sigdelset(&all_masked, SIGBUS);
sigdelset(&all_masked, SIGSEGV);
OPENSSL_armcap_P = 0;
memset(&ill_act, 0, sizeof(ill_act));
ill_act.sa_handler = ill_handler;
ill_act.sa_mask = all_masked;
sigprocmask(SIG_SETMASK, &ill_act.sa_mask, &oset);
sigaction(SIGILL, &ill_act, &ill_oact);
if (getauxval != NULL) {
if (getauxval(HWCAP) & HWCAP_NEON) {
unsigned long hwcap = getauxval(HWCAP_CE);
OPENSSL_armcap_P |= ARMV7_NEON;
if (hwcap & HWCAP_CE_AES)
OPENSSL_armcap_P |= ARMV8_AES;
if (hwcap & HWCAP_CE_PMULL)
OPENSSL_armcap_P |= ARMV8_PMULL;
if (hwcap & HWCAP_CE_SHA1)
OPENSSL_armcap_P |= ARMV8_SHA1;
if (hwcap & HWCAP_CE_SHA256)
OPENSSL_armcap_P |= ARMV8_SHA256;
}
} else if (sigsetjmp(ill_jmp, 1) == 0) {
_armv7_neon_probe();
OPENSSL_armcap_P |= ARMV7_NEON;
if (sigsetjmp(ill_jmp, 1) == 0) {
_armv8_pmull_probe();
OPENSSL_armcap_P |= ARMV8_PMULL | ARMV8_AES;
} else if (sigsetjmp(ill_jmp, 1) == 0) {
_armv8_aes_probe();
OPENSSL_armcap_P |= ARMV8_AES;
}
if (sigsetjmp(ill_jmp, 1) == 0) {
_armv8_sha1_probe();
OPENSSL_armcap_P |= ARMV8_SHA1;
}
if (sigsetjmp(ill_jmp, 1) == 0) {
_armv8_sha256_probe();
OPENSSL_armcap_P |= ARMV8_SHA256;
}
}
if (sigsetjmp(ill_jmp, 1) == 0) {
_armv7_tick();
OPENSSL_armcap_P |= ARMV7_TICK;
}
sigaction(SIGILL, &ill_oact, NULL);
sigprocmask(SIG_SETMASK, &oset, NULL);
}
#endif
@@ -0,0 +1,208 @@
#include "arm_arch.h"
.text
.code 32
.align 5
.global OPENSSL_atomic_add
.type OPENSSL_atomic_add,@function
OPENSSL_atomic_add:
#if __ARM_ARCH__>=6
.Ladd: ldrex r2,[r0]
add r3,r2,r1
strex r2,r3,[r0]
cmp r2,#0
bne .Ladd
mov r0,r3
bx lr
#else
stmdb sp!,{r4-r6,lr}
ldr r2,.Lspinlock
adr r3,.Lspinlock
mov r4,r0
mov r5,r1
add r6,r3,r2 @ &spinlock
b .+8
.Lspin: bl sched_yield
mov r0,#-1
swp r0,r0,[r6]
cmp r0,#0
bne .Lspin
ldr r2,[r4]
add r2,r2,r5
str r2,[r4]
str r0,[r6] @ release spinlock
ldmia sp!,{r4-r6,lr}
tst lr,#1
moveq pc,lr
.word 0xe12fff1e @ bx lr
#endif
.size OPENSSL_atomic_add,.-OPENSSL_atomic_add
.global OPENSSL_cleanse
.type OPENSSL_cleanse,@function
OPENSSL_cleanse:
eor ip,ip,ip
cmp r1,#7
subhs r1,r1,#4
bhs .Lot
cmp r1,#0
beq .Lcleanse_done
.Little:
strb ip,[r0],#1
subs r1,r1,#1
bhi .Little
b .Lcleanse_done
.Lot: tst r0,#3
beq .Laligned
strb ip,[r0],#1
sub r1,r1,#1
b .Lot
.Laligned:
str ip,[r0],#4
subs r1,r1,#4
bhs .Laligned
adds r1,r1,#4
bne .Little
.Lcleanse_done:
#if __ARM_ARCH__>=5
bx lr
#else
tst lr,#1
moveq pc,lr
.word 0xe12fff1e @ bx lr
#endif
.size OPENSSL_cleanse,.-OPENSSL_cleanse
#if __ARM_MAX_ARCH__>=7
.arch armv7-a
.fpu neon
.align 5
.global _armv7_neon_probe
.type _armv7_neon_probe,@function
_armv7_neon_probe:
vorr q0,q0,q0
bx lr
.size _armv7_neon_probe,.-_armv7_neon_probe
.global _armv7_tick
.type _armv7_tick,@function
_armv7_tick:
mrrc p15,1,r0,r1,c14 @ CNTVCT
bx lr
.size _armv7_tick,.-_armv7_tick
.global _armv8_aes_probe
.type _armv8_aes_probe,@function
_armv8_aes_probe:
.byte 0x00,0x03,0xb0,0xf3 @ aese.8 q0,q0
bx lr
.size _armv8_aes_probe,.-_armv8_aes_probe
.global _armv8_sha1_probe
.type _armv8_sha1_probe,@function
_armv8_sha1_probe:
.byte 0x40,0x0c,0x00,0xf2 @ sha1c.32 q0,q0,q0
bx lr
.size _armv8_sha1_probe,.-_armv8_sha1_probe
.global _armv8_sha256_probe
.type _armv8_sha256_probe,@function
_armv8_sha256_probe:
.byte 0x40,0x0c,0x00,0xf3 @ sha256h.32 q0,q0,q0
bx lr
.size _armv8_sha256_probe,.-_armv8_sha256_probe
.global _armv8_pmull_probe
.type _armv8_pmull_probe,@function
_armv8_pmull_probe:
.byte 0x00,0x0e,0xa0,0xf2 @ vmull.p64 q0,d0,d0
bx lr
.size _armv8_pmull_probe,.-_armv8_pmull_probe
#endif
.global OPENSSL_wipe_cpu
.type OPENSSL_wipe_cpu,@function
OPENSSL_wipe_cpu:
#if __ARM_MAX_ARCH__>=7
ldr r0,.LOPENSSL_armcap
adr r1,.LOPENSSL_armcap
ldr r0,[r1,r0]
#endif
eor r2,r2,r2
eor r3,r3,r3
eor ip,ip,ip
#if __ARM_MAX_ARCH__>=7
tst r0,#1
beq .Lwipe_done
veor q0, q0, q0
veor q1, q1, q1
veor q2, q2, q2
veor q3, q3, q3
veor q8, q8, q8
veor q9, q9, q9
veor q10, q10, q10
veor q11, q11, q11
veor q12, q12, q12
veor q13, q13, q13
veor q14, q14, q14
veor q15, q15, q15
.Lwipe_done:
#endif
mov r0,sp
#if __ARM_ARCH__>=5
bx lr
#else
tst lr,#1
moveq pc,lr
.word 0xe12fff1e @ bx lr
#endif
.size OPENSSL_wipe_cpu,.-OPENSSL_wipe_cpu
.global OPENSSL_instrument_bus
.type OPENSSL_instrument_bus,@function
OPENSSL_instrument_bus:
eor r0,r0,r0
#if __ARM_ARCH__>=5
bx lr
#else
tst lr,#1
moveq pc,lr
.word 0xe12fff1e @ bx lr
#endif
.size OPENSSL_instrument_bus,.-OPENSSL_instrument_bus
.global OPENSSL_instrument_bus2
.type OPENSSL_instrument_bus2,@function
OPENSSL_instrument_bus2:
eor r0,r0,r0
#if __ARM_ARCH__>=5
bx lr
#else
tst lr,#1
moveq pc,lr
.word 0xe12fff1e @ bx lr
#endif
.size OPENSSL_instrument_bus2,.-OPENSSL_instrument_bus2
.align 5
#if __ARM_MAX_ARCH__>=7
.LOPENSSL_armcap:
.word OPENSSL_armcap_P-.LOPENSSL_armcap
#endif
#if __ARM_ARCH__>=6
.align 5
#else
.Lspinlock:
.word atomic_add_spinlock-.Lspinlock
.align 5
.data
.align 2
atomic_add_spinlock:
.word 0
#endif
.lcomm OPENSSL_armcap_P,4,4
@@ -0,0 +1,269 @@
/* crypto/asn1/a_bitstr.c */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.]
*/
#include <limits.h>
#include <stdio.h>
#include "cryptlib.h"
#include <openssl/asn1.h>
int ASN1_BIT_STRING_set(ASN1_BIT_STRING *x, unsigned char *d, int len)
{
return M_ASN1_BIT_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 = M_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 = (unsigned char *)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;
if (ret->data != NULL)
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 ((ret != NULL) && ((a == NULL) || (*a != ret)))
M_ASN1_BIT_STRING_free(ret);
return (NULL);
}
/*
* These next 2 functions from Goetz Babin-Ebell <babinebell@trustcenter.de>
*/
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 */
if (a->data == NULL)
c = (unsigned char *)OPENSSL_malloc(w + 1);
else
c = (unsigned char *)OPENSSL_realloc_clean(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(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(ASN1_BIT_STRING *a,
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;
}
@@ -0,0 +1,125 @@
/* crypto/asn1/a_bool.c */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.]
*/
#include <stdio.h>
#include "cryptlib.h"
#include <openssl/asn1t.h>
int i2d_ASN1_BOOLEAN(int a, unsigned char **pp)
{
int r;
unsigned char *p, *allocated = NULL;
r = ASN1_object_size(0, 1, V_ASN1_BOOLEAN);
if (pp == NULL)
return (r);
if (*pp == NULL) {
if ((p = allocated = OPENSSL_malloc(r)) == NULL) {
ASN1err(ASN1_F_I2D_ASN1_BOOLEAN, ERR_R_MALLOC_FAILURE);
return 0;
}
} else {
p = *pp;
}
ASN1_put_object(&p, 0, 1, V_ASN1_BOOLEAN, V_ASN1_UNIVERSAL);
*p = (unsigned char)a;
/*
* If a new buffer was allocated, just return it back.
* If not, return the incremented buffer pointer.
*/
*pp = allocated != NULL ? allocated : p + 1;
return r;
}
int d2i_ASN1_BOOLEAN(int *a, const unsigned char **pp, long length)
{
int ret = -1;
const unsigned char *p;
long len;
int inf, tag, xclass;
int i = 0;
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_BOOLEAN) {
i = ASN1_R_EXPECTING_A_BOOLEAN;
goto err;
}
if (len != 1) {
i = ASN1_R_BOOLEAN_IS_WRONG_LENGTH;
goto err;
}
ret = (int)*(p++);
if (a != NULL)
(*a) = ret;
*pp = p;
return (ret);
err:
ASN1err(ASN1_F_D2I_ASN1_BOOLEAN, i);
return (ret);
}
@@ -0,0 +1,334 @@
/* crypto/asn1/a_bytes.c */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.]
*/
#include <stdio.h>
#include "cryptlib.h"
#include <openssl/asn1.h>
static int asn1_collate_primitive(ASN1_STRING *a, ASN1_const_CTX *c,
int depth);
static ASN1_STRING *int_d2i_ASN1_bytes(ASN1_STRING **a,
const unsigned char **pp, long length,
int Ptag, int Pclass, int depth,
int *perr);
/*
* type is a 'bitmap' of acceptable string types.
*/
ASN1_STRING *d2i_ASN1_type_bytes(ASN1_STRING **a, const unsigned char **pp,
long length, int type)
{
ASN1_STRING *ret = NULL;
const unsigned char *p;
unsigned char *s;
long len;
int inf, tag, xclass;
int i = 0;
p = *pp;
inf = ASN1_get_object(&p, &len, &tag, &xclass, length);
if (inf & 0x80)
goto err;
if (tag >= 32) {
i = ASN1_R_TAG_VALUE_TOO_HIGH;
goto err;
}
if (!(ASN1_tag2bit(tag) & type)) {
i = ASN1_R_WRONG_TYPE;
goto err;
}
/* If a bit-string, exit early */
if (tag == V_ASN1_BIT_STRING)
return (d2i_ASN1_BIT_STRING(a, pp, length));
if ((a == NULL) || ((*a) == NULL)) {
if ((ret = ASN1_STRING_new()) == NULL)
return (NULL);
} else
ret = (*a);
if (len != 0) {
s = OPENSSL_malloc((int)len + 1);
if (s == NULL) {
i = ERR_R_MALLOC_FAILURE;
goto err;
}
memcpy(s, p, (int)len);
s[len] = '\0';
p += len;
} else
s = NULL;
if (ret->data != NULL)
OPENSSL_free(ret->data);
ret->length = (int)len;
ret->data = s;
ret->type = tag;
if (a != NULL)
(*a) = ret;
*pp = p;
return (ret);
err:
ASN1err(ASN1_F_D2I_ASN1_TYPE_BYTES, i);
if ((ret != NULL) && ((a == NULL) || (*a != ret)))
ASN1_STRING_free(ret);
return (NULL);
}
int i2d_ASN1_bytes(ASN1_STRING *a, unsigned char **pp, int tag, int xclass)
{
int ret, r, constructed;
unsigned char *p;
if (a == NULL)
return (0);
if (tag == V_ASN1_BIT_STRING)
return (i2d_ASN1_BIT_STRING(a, pp));
ret = a->length;
r = ASN1_object_size(0, ret, tag);
if (pp == NULL)
return (r);
p = *pp;
if ((tag == V_ASN1_SEQUENCE) || (tag == V_ASN1_SET))
constructed = 1;
else
constructed = 0;
ASN1_put_object(&p, constructed, ret, tag, xclass);
memcpy(p, a->data, a->length);
p += a->length;
*pp = p;
return (r);
}
/*
* Maximum recursion depth of d2i_ASN1_bytes(): much more than should be
* encountered in pratice.
*/
#define ASN1_BYTES_MAXDEPTH 20
ASN1_STRING *d2i_ASN1_bytes(ASN1_STRING **a, const unsigned char **pp,
long length, int Ptag, int Pclass)
{
int err = 0;
ASN1_STRING *s = int_d2i_ASN1_bytes(a, pp, length, Ptag, Pclass, 0, &err);
if (err != 0)
ASN1err(ASN1_F_D2I_ASN1_BYTES, err);
return s;
}
static ASN1_STRING *int_d2i_ASN1_bytes(ASN1_STRING **a,
const unsigned char **pp, long length,
int Ptag, int Pclass,
int depth, int *perr)
{
ASN1_STRING *ret = NULL;
const unsigned char *p;
unsigned char *s;
long len;
int inf, tag, xclass;
if (depth > ASN1_BYTES_MAXDEPTH) {
*perr = ASN1_R_NESTED_ASN1_STRING;
return NULL;
}
if ((a == NULL) || ((*a) == NULL)) {
if ((ret = ASN1_STRING_new()) == NULL)
return (NULL);
} else
ret = (*a);
p = *pp;
inf = ASN1_get_object(&p, &len, &tag, &xclass, length);
if (inf & 0x80) {
*perr = ASN1_R_BAD_OBJECT_HEADER;
goto err;
}
if (tag != Ptag) {
*perr = ASN1_R_WRONG_TAG;
goto err;
}
if (inf & V_ASN1_CONSTRUCTED) {
ASN1_const_CTX c;
c.error = 0;
c.pp = pp;
c.p = p;
c.inf = inf;
c.slen = len;
c.tag = Ptag;
c.xclass = Pclass;
c.max = (length == 0) ? 0 : (p + length);
if (!asn1_collate_primitive(ret, &c, depth)) {
*perr = c.error;
goto err;
} else {
p = c.p;
}
} else {
if (len != 0) {
if ((ret->length < len) || (ret->data == NULL)) {
s = OPENSSL_malloc((int)len + 1);
if (s == NULL) {
*perr = ERR_R_MALLOC_FAILURE;
goto err;
}
if (ret->data != NULL)
OPENSSL_free(ret->data);
} else
s = ret->data;
memcpy(s, p, (int)len);
s[len] = '\0';
p += len;
} else {
s = NULL;
if (ret->data != NULL)
OPENSSL_free(ret->data);
}
ret->length = (int)len;
ret->data = s;
ret->type = Ptag;
}
if (a != NULL)
(*a) = ret;
*pp = p;
return (ret);
err:
if ((ret != NULL) && ((a == NULL) || (*a != ret)))
ASN1_STRING_free(ret);
return (NULL);
}
/*
* We are about to parse 0..n d2i_ASN1_bytes objects, we are to collapse them
* into the one structure that is then returned
*/
/*
* There have been a few bug fixes for this function from Paul Keogh
* <paul.keogh@sse.ie>, many thanks to him
*/
static int asn1_collate_primitive(ASN1_STRING *a, ASN1_const_CTX *c,
int depth)
{
ASN1_STRING *os = NULL;
BUF_MEM b;
int num;
b.length = 0;
b.max = 0;
b.data = NULL;
if (a == NULL) {
c->error = ERR_R_PASSED_NULL_PARAMETER;
goto err;
}
num = 0;
for (;;) {
if (c->inf & 1) {
c->eos = ASN1_const_check_infinite_end(&c->p,
(long)(c->max - c->p));
if (c->eos)
break;
} else {
if (c->slen <= 0)
break;
}
c->q = c->p;
if (int_d2i_ASN1_bytes(&os, &c->p, c->max - c->p, c->tag, c->xclass,
depth + 1, &c->error) == NULL) {
goto err;
}
if (!BUF_MEM_grow_clean(&b, num + os->length)) {
c->error = ERR_R_BUF_LIB;
goto err;
}
memcpy(&(b.data[num]), os->data, os->length);
if (!(c->inf & 1))
c->slen -= (c->p - c->q);
num += os->length;
}
if (!asn1_const_Finish(c))
goto err;
a->length = num;
if (a->data != NULL)
OPENSSL_free(a->data);
a->data = (unsigned char *)b.data;
if (os != NULL)
ASN1_STRING_free(os);
return (1);
err:
if (os != NULL)
ASN1_STRING_free(os);
if (b.data != NULL)
OPENSSL_free(b.data);
return (0);
}
@@ -0,0 +1,284 @@
/* crypto/asn1/a_d2i_fp.c */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.]
*/
#include <stdio.h>
#include <limits.h>
#include "cryptlib.h"
#include <openssl/buffer.h>
#include <openssl/asn1_mac.h>
static int asn1_d2i_read_bio(BIO *in, BUF_MEM **pb);
#ifndef NO_OLD_ASN1
# ifndef OPENSSL_NO_FP_API
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:
if (b != NULL)
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:
if (b != NULL)
BUF_MEM_free(b);
return (ret);
}
#ifndef OPENSSL_NO_FP_API
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)
static int asn1_d2i_read_bio(BIO *in, BUF_MEM **pb)
{
BUF_MEM *b;
unsigned char *p;
int i;
ASN1_const_CTX c;
size_t want = HEADER_SIZE;
int eos = 0;
size_t off = 0;
size_t len = 0;
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]);
c.p = p;
c.inf = ASN1_get_object(&(c.p), &(c.slen), &(c.tag), &(c.xclass),
len - off);
if (c.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 = c.p - p; /* header length */
off += i; /* end of data */
if (c.inf & 1) {
/* no data body so go round again */
eos++;
if (eos < 0) {
ASN1err(ASN1_F_ASN1_D2I_READ_BIO, ASN1_R_HEADER_TOO_LONG);
goto err;
}
want = HEADER_SIZE;
} else if (eos && (c.slen == 0) && (c.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 c.slen bytes of data */
want = c.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 + c.slen < off) {
ASN1err(ASN1_F_ASN1_D2I_READ_BIO, ASN1_R_TOO_LONG);
goto err;
}
off += c.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:
if (b != NULL)
BUF_MEM_free(b);
return -1;
}
@@ -0,0 +1,115 @@
/* crypto/asn1/a_digest.c */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.]
*/
#include <stdio.h>
#include <time.h>
#include "cryptlib.h"
#ifndef NO_SYS_TYPES_H
# include <sys/types.h>
#endif
#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 = (unsigned char *)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);
}
@@ -0,0 +1,117 @@
/* crypto/asn1/a_dup.c */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.]
*/
#include <stdio.h>
#include "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);
}
@@ -0,0 +1,181 @@
/* crypto/asn1/a_enum.c */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.]
*/
#include <stdio.h>
#include "cryptlib.h"
#include <openssl/asn1.h>
#include <openssl/bn.h>
/*
* Code for ENUMERATED type: identical to INTEGER apart from a different tag.
* for comments on encoding see a_int.c
*/
int ASN1_ENUMERATED_set(ASN1_ENUMERATED *a, long v)
{
int j, k;
unsigned int i;
unsigned char buf[sizeof(long) + 1];
long d;
a->type = V_ASN1_ENUMERATED;
if (a->length < (int)(sizeof(long) + 1)) {
if (a->data != NULL)
OPENSSL_free(a->data);
if ((a->data =
(unsigned char *)OPENSSL_malloc(sizeof(long) + 1)) != NULL)
memset((char *)a->data, 0, sizeof(long) + 1);
}
if (a->data == NULL) {
ASN1err(ASN1_F_ASN1_ENUMERATED_SET, ERR_R_MALLOC_FAILURE);
return (0);
}
d = v;
if (d < 0) {
d = -d;
a->type = V_ASN1_NEG_ENUMERATED;
}
for (i = 0; i < sizeof(long); i++) {
if (d == 0)
break;
buf[i] = (int)d & 0xff;
d >>= 8;
}
j = 0;
for (k = i - 1; k >= 0; k--)
a->data[j++] = buf[k];
a->length = j;
return (1);
}
long ASN1_ENUMERATED_get(ASN1_ENUMERATED *a)
{
int neg = 0, i;
long r = 0;
if (a == NULL)
return (0L);
i = a->type;
if (i == V_ASN1_NEG_ENUMERATED)
neg = 1;
else if (i != V_ASN1_ENUMERATED)
return -1;
if (a->length > (int)sizeof(long)) {
/* hmm... a bit ugly */
return (0xffffffffL);
}
if (a->data == NULL)
return 0;
for (i = 0; i < a->length; i++) {
r <<= 8;
r |= (unsigned char)a->data[i];
}
if (neg)
r = -r;
return (r);
}
ASN1_ENUMERATED *BN_to_ASN1_ENUMERATED(BIGNUM *bn, ASN1_ENUMERATED *ai)
{
ASN1_ENUMERATED *ret;
int len, j;
if (ai == NULL)
ret = M_ASN1_ENUMERATED_new();
else
ret = ai;
if (ret == NULL) {
ASN1err(ASN1_F_BN_TO_ASN1_ENUMERATED, ERR_R_NESTED_ASN1_ERROR);
goto err;
}
if (BN_is_negative(bn))
ret->type = V_ASN1_NEG_ENUMERATED;
else
ret->type = V_ASN1_ENUMERATED;
j = BN_num_bits(bn);
len = ((j == 0) ? 0 : ((j / 8) + 1));
if (ret->length < len + 4) {
unsigned char *new_data = OPENSSL_realloc(ret->data, len + 4);
if (!new_data) {
ASN1err(ASN1_F_BN_TO_ASN1_ENUMERATED, ERR_R_MALLOC_FAILURE);
goto err;
}
ret->data = new_data;
}
ret->length = BN_bn2bin(bn, ret->data);
return (ret);
err:
if (ret != ai)
M_ASN1_ENUMERATED_free(ret);
return (NULL);
}
BIGNUM *ASN1_ENUMERATED_to_BN(ASN1_ENUMERATED *ai, BIGNUM *bn)
{
BIGNUM *ret;
if ((ret = BN_bin2bn(ai->data, ai->length, bn)) == NULL)
ASN1err(ASN1_F_ASN1_ENUMERATED_TO_BN, ASN1_R_BN_LIB);
else if (ai->type == V_ASN1_NEG_ENUMERATED)
BN_set_negative(ret, 1);
return (ret);
}
@@ -0,0 +1,312 @@
/* crypto/asn1/a_gentm.c */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.]
*/
/*
* GENERALIZEDTIME implementation, written by Steve Henson. Based on UTCTIME
*/
#include <stdio.h>
#include <time.h>
#include "cryptlib.h"
#include "o_time.h"
#include <openssl/asn1.h>
#include "asn1_locl.h"
#if 0
int i2d_ASN1_GENERALIZEDTIME(ASN1_GENERALIZEDTIME *a, unsigned char **pp)
{
# ifdef CHARSET_EBCDIC
/* KLUDGE! We convert to ascii before writing DER */
int len;
char tmp[24];
ASN1_STRING tmpstr = *(ASN1_STRING *)a;
len = tmpstr.length;
ebcdic2ascii(tmp, tmpstr.data, (len >= sizeof(tmp)) ? sizeof(tmp) : len);
tmpstr.data = tmp;
a = (ASN1_GENERALIZEDTIME *)&tmpstr;
# endif
return (i2d_ASN1_bytes((ASN1_STRING *)a, pp,
V_ASN1_GENERALIZEDTIME, V_ASN1_UNIVERSAL));
}
ASN1_GENERALIZEDTIME *d2i_ASN1_GENERALIZEDTIME(ASN1_GENERALIZEDTIME **a,
unsigned char **pp,
long length)
{
ASN1_GENERALIZEDTIME *ret = NULL;
ret =
(ASN1_GENERALIZEDTIME *)d2i_ASN1_bytes((ASN1_STRING **)a, pp, length,
V_ASN1_GENERALIZEDTIME,
V_ASN1_UNIVERSAL);
if (ret == NULL) {
ASN1err(ASN1_F_D2I_ASN1_GENERALIZEDTIME, ERR_R_NESTED_ASN1_ERROR);
return (NULL);
}
# ifdef CHARSET_EBCDIC
ascii2ebcdic(ret->data, ret->data, ret->length);
# endif
if (!ASN1_GENERALIZEDTIME_check(ret)) {
ASN1err(ASN1_F_D2I_ASN1_GENERALIZEDTIME, ASN1_R_INVALID_TIME_FORMAT);
goto err;
}
return (ret);
err:
if ((ret != NULL) && ((a == NULL) || (*a != ret)))
M_ASN1_GENERALIZEDTIME_free(ret);
return (NULL);
}
#endif
int asn1_generalizedtime_to_tm(struct tm *tm, const ASN1_GENERALIZEDTIME *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 };
char *a;
int n, i, l, o;
if (d->type != V_ASN1_GENERALIZEDTIME)
return (0);
l = d->length;
a = (char *)d->data;
o = 0;
/*
* 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 < 13)
goto err;
for (i = 0; i < 7; i++) {
if ((i == 6) && ((a[o] == 'Z') || (a[o] == '+') || (a[o] == '-'))) {
i++;
if (tm)
tm->tm_sec = 0;
break;
}
if ((a[o] < '0') || (a[o] > '9'))
goto err;
n = a[o] - '0';
if (++o > l)
goto err;
if ((a[o] < '0') || (a[o] > '9'))
goto err;
n = (n * 10) + a[o] - '0';
if (++o > l)
goto err;
if ((n < min[i]) || (n > max[i]))
goto err;
if (tm) {
switch (i) {
case 0:
tm->tm_year = n * 100 - 1900;
break;
case 1:
tm->tm_year += n;
break;
case 2:
tm->tm_mon = n - 1;
break;
case 3:
tm->tm_mday = n;
break;
case 4:
tm->tm_hour = n;
break;
case 5:
tm->tm_min = n;
break;
case 6:
tm->tm_sec = n;
break;
}
}
}
/*
* Optional fractional seconds: decimal point followed by one or more
* digits.
*/
if (a[o] == '.') {
if (++o > l)
goto err;
i = o;
while ((a[o] >= '0') && (a[o] <= '9') && (o <= l))
o++;
/* Must have at least one digit after decimal point */
if (i == o)
goto err;
}
if (a[o] == 'Z')
o++;
else if ((a[o] == '+') || (a[o] == '-')) {
int offsign = a[o] == '-' ? 1 : -1, offset = 0;
o++;
if (o + 4 > l)
goto err;
for (i = 7; i < 9; i++) {
if ((a[o] < '0') || (a[o] > '9'))
goto err;
n = a[o] - '0';
o++;
if ((a[o] < '0') || (a[o] > '9'))
goto err;
n = (n * 10) + a[o] - '0';
if ((n < min[i]) || (n > max[i]))
goto err;
if (tm) {
if (i == 7)
offset = n * 3600;
else if (i == 8)
offset += n * 60;
}
o++;
}
if (offset && !OPENSSL_gmtime_adj(tm, 0, offset * offsign))
return 0;
} else if (a[o]) {
/* Missing time zone information. */
goto err;
}
return (o == l);
err:
return (0);
}
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;
if (ASN1_GENERALIZEDTIME_check(&t)) {
if (s != NULL) {
if (!ASN1_STRING_set((ASN1_STRING *)s,
(unsigned char *)str, t.length))
return 0;
s->type = V_ASN1_GENERALIZEDTIME;
}
return (1);
} else
return (0);
}
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)
{
char *p;
struct tm *ts;
struct tm data;
size_t len = 20;
if (s == NULL)
s = M_ASN1_GENERALIZEDTIME_new();
if (s == NULL)
return (NULL);
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;
}
p = (char *)s->data;
if ((p == NULL) || ((size_t)s->length < len)) {
p = OPENSSL_malloc(len);
if (p == NULL) {
ASN1err(ASN1_F_ASN1_GENERALIZEDTIME_ADJ, ERR_R_MALLOC_FAILURE);
return (NULL);
}
if (s->data != NULL)
OPENSSL_free(s->data);
s->data = (unsigned char *)p;
}
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);
s->length = strlen(p);
s->type = V_ASN1_GENERALIZEDTIME;
#ifdef CHARSET_EBCDIC_not
ebcdic2ascii(s->data, s->data, s->length);
#endif
return (s);
}
@@ -0,0 +1,160 @@
/* crypto/asn1/a_i2d_fp.c */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.]
*/
#include <stdio.h>
#include "cryptlib.h"
#include <openssl/buffer.h>
#include <openssl/asn1.h>
#ifndef NO_OLD_ASN1
# ifndef OPENSSL_NO_FP_API
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 = (char *)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_FP_API
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);
}
@@ -0,0 +1,464 @@
/* crypto/asn1/a_int.c */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.]
*/
#include <stdio.h>
#include "cryptlib.h"
#include <openssl/asn1.h>
#include <openssl/bn.h>
ASN1_INTEGER *ASN1_INTEGER_dup(const ASN1_INTEGER *x)
{
return M_ASN1_INTEGER_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 an ASN1 INTEGER into its content encoding.
* 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: V_ASN1_INTEGER for positive and V_ASN1_NEG_INTEGER for negative.
*
* 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.
*/
int i2c_ASN1_INTEGER(ASN1_INTEGER *a, unsigned char **pp)
{
int pad = 0, ret, i, neg;
unsigned char *p, *n, pb = 0;
if (a == NULL)
return (0);
neg = a->type & V_ASN1_NEG;
if (a->length == 0)
ret = 1;
else {
ret = a->length;
i = a->data[0];
if (ret == 1 && i == 0)
neg = 0;
if (!neg && (i > 127)) {
pad = 1;
pb = 0;
} else if (neg) {
if (i > 128) {
pad = 1;
pb = 0xFF;
} else if (i == 128) {
/*
* Special case: if any other bytes non zero we pad:
* otherwise we don't.
*/
for (i = 1; i < a->length; i++)
if (a->data[i]) {
pad = 1;
pb = 0xFF;
break;
}
}
}
ret += pad;
}
if (pp == NULL)
return (ret);
p = *pp;
if (pad)
*(p++) = pb;
if (a->length == 0)
*(p++) = 0;
else if (!neg)
memcpy(p, a->data, (unsigned int)a->length);
else {
/* Begin at the end of the encoding */
n = a->data + a->length - 1;
p += a->length - 1;
i = a->length;
/* Copy zeros to destination as long as source is zero */
while (!*n && i > 1) {
*(p--) = 0;
n--;
i--;
}
/* Complement and increment next octet */
*(p--) = ((*(n--)) ^ 0xff) + 1;
i--;
/* Complement any octets left */
for (; i > 0; i--)
*(p--) = *(n--) ^ 0xff;
}
*pp += ret;
return (ret);
}
/* Convert just 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;
const unsigned char *p, *pend;
unsigned char *to, *s;
int i;
if ((a == NULL) || ((*a) == NULL)) {
if ((ret = M_ASN1_INTEGER_new()) == NULL)
return (NULL);
ret->type = V_ASN1_INTEGER;
} else
ret = (*a);
p = *pp;
pend = p + len;
/*
* We must OPENSSL_malloc stuff, even for 0 bytes otherwise it signifies
* a missing NULL parameter.
*/
s = (unsigned char *)OPENSSL_malloc((int)len + 1);
if (s == NULL) {
i = ERR_R_MALLOC_FAILURE;
goto err;
}
to = s;
if (!len) {
/*
* Strictly speaking this is an illegal INTEGER but we tolerate it.
*/
ret->type = V_ASN1_INTEGER;
} else if (*p & 0x80) { /* a negative number */
ret->type = V_ASN1_NEG_INTEGER;
if ((*p == 0xff) && (len != 1)) {
p++;
len--;
}
i = len;
p += i - 1;
to += i - 1;
while ((!*p) && i) {
*(to--) = 0;
i--;
p--;
}
/*
* Special case: if all zeros then the number will be of the form FF
* followed by n zero bytes: this corresponds to 1 followed by n zero
* bytes. We've already written n zeros so we just append an extra
* one and set the first byte to a 1. This is treated separately
* because it is the only case where the number of bytes is larger
* than len.
*/
if (!i) {
*s = 1;
s[len] = 0;
len++;
} else {
*(to--) = (*(p--) ^ 0xff) + 1;
i--;
for (; i > 0; i--)
*(to--) = *(p--) ^ 0xff;
}
} else {
ret->type = V_ASN1_INTEGER;
if ((*p == 0) && (len != 1)) {
p++;
len--;
}
memcpy(s, p, (int)len);
}
if (ret->data != NULL)
OPENSSL_free(ret->data);
ret->data = s;
ret->length = (int)len;
if (a != NULL)
(*a) = ret;
*pp = pend;
return (ret);
err:
ASN1err(ASN1_F_C2I_ASN1_INTEGER, i);
if ((ret != NULL) && ((a == NULL) || (*a != ret)))
M_ASN1_INTEGER_free(ret);
return (NULL);
}
/*
* 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 = M_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 = (unsigned char *)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;
}
if (ret->data != NULL)
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 ((ret != NULL) && ((a == NULL) || (*a != ret)))
M_ASN1_INTEGER_free(ret);
return (NULL);
}
int ASN1_INTEGER_set(ASN1_INTEGER *a, long v)
{
int j, k;
unsigned int i;
unsigned char buf[sizeof(long) + 1];
long d;
a->type = V_ASN1_INTEGER;
if (a->length < (int)(sizeof(long) + 1)) {
if (a->data != NULL)
OPENSSL_free(a->data);
if ((a->data =
(unsigned char *)OPENSSL_malloc(sizeof(long) + 1)) != NULL)
memset((char *)a->data, 0, sizeof(long) + 1);
}
if (a->data == NULL) {
ASN1err(ASN1_F_ASN1_INTEGER_SET, ERR_R_MALLOC_FAILURE);
return (0);
}
d = v;
if (d < 0) {
d = -d;
a->type = V_ASN1_NEG_INTEGER;
}
for (i = 0; i < sizeof(long); i++) {
if (d == 0)
break;
buf[i] = (int)d & 0xff;
d >>= 8;
}
j = 0;
for (k = i - 1; k >= 0; k--)
a->data[j++] = buf[k];
a->length = j;
return (1);
}
long ASN1_INTEGER_get(const ASN1_INTEGER *a)
{
int neg = 0, i;
long r = 0;
if (a == NULL)
return (0L);
i = a->type;
if (i == V_ASN1_NEG_INTEGER)
neg = 1;
else if (i != V_ASN1_INTEGER)
return -1;
if (a->length > (int)sizeof(long)) {
/* hmm... a bit ugly, return all ones */
return -1;
}
if (a->data == NULL)
return 0;
for (i = 0; i < a->length; i++) {
r <<= 8;
r |= (unsigned char)a->data[i];
}
if (neg)
r = -r;
return (r);
}
ASN1_INTEGER *BN_to_ASN1_INTEGER(const BIGNUM *bn, ASN1_INTEGER *ai)
{
ASN1_INTEGER *ret;
int len, j;
if (ai == NULL)
ret = M_ASN1_INTEGER_new();
else
ret = ai;
if (ret == NULL) {
ASN1err(ASN1_F_BN_TO_ASN1_INTEGER, ERR_R_NESTED_ASN1_ERROR);
goto err;
}
if (BN_is_negative(bn) && !BN_is_zero(bn))
ret->type = V_ASN1_NEG_INTEGER;
else
ret->type = V_ASN1_INTEGER;
j = BN_num_bits(bn);
len = ((j == 0) ? 0 : ((j / 8) + 1));
if (ret->length < len + 4) {
unsigned char *new_data = OPENSSL_realloc(ret->data, len + 4);
if (!new_data) {
ASN1err(ASN1_F_BN_TO_ASN1_INTEGER, ERR_R_MALLOC_FAILURE);
goto err;
}
ret->data = new_data;
}
ret->length = BN_bn2bin(bn, ret->data);
/* Correct zero case */
if (!ret->length) {
ret->data[0] = 0;
ret->length = 1;
}
return (ret);
err:
if (ret != ai)
M_ASN1_INTEGER_free(ret);
return (NULL);
}
BIGNUM *ASN1_INTEGER_to_BN(const ASN1_INTEGER *ai, BIGNUM *bn)
{
BIGNUM *ret;
if ((ret = BN_bin2bn(ai->data, ai->length, bn)) == NULL)
ASN1err(ASN1_F_ASN1_INTEGER_TO_BN, ASN1_R_BN_LIB);
else if (ai->type == V_ASN1_NEG_INTEGER)
BN_set_negative(ret, 1);
return (ret);
}
IMPLEMENT_STACK_OF(ASN1_INTEGER)
IMPLEMENT_ASN1_SET_OF(ASN1_INTEGER)
@@ -0,0 +1,423 @@
/* a_mbstr.c */
/*
* Written by Dr Stephen N Henson (steve@openssl.org) 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 <ctype.h>
#include "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);
static int is_printable(unsigned long value);
/*
* 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 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_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;
if (dest->data) {
dest->length = 0;
OPENSSL_free(dest->data);
dest->data = NULL;
}
dest->type = str_type;
} else {
free_out = 1;
dest = ASN1_STRING_type_new(str_type);
if (!dest) {
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))) {
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;
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.
*/
#ifndef CHARSET_EBCDIC
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;
#else /* CHARSET_EBCDIC */
if ((ch >= os_toascii['a']) && (ch <= os_toascii['z']))
return 1;
if ((ch >= os_toascii['A']) && (ch <= os_toascii['Z']))
return 1;
if ((ch >= os_toascii['0']) && (ch <= os_toascii['9']))
return 1;
if ((ch == os_toascii[' ']) || strchr("'()+,-./:=?", os_toebcdic[ch]))
return 1;
#endif /* CHARSET_EBCDIC */
return 0;
}
@@ -0,0 +1,417 @@
/* crypto/asn1/a_object.c */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.]
*/
#include <stdio.h>
#include <limits.h>
#include "cryptlib.h"
#include <openssl/buffer.h>
#include <openssl/asn1.h>
#include <openssl/objects.h>
#include <openssl/bn.h>
int i2d_ASN1_OBJECT(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 ((c < '0') || (c > '9')) {
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)
bl = BN_new();
if (!bl || !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)
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);
if (bl)
BN_free(bl);
return (len);
err:
if (tmp != ftmp)
OPENSSL_free(tmp);
if (bl)
BN_free(bl);
return (0);
}
int i2t_ASN1_OBJECT(char *buf, int buf_len, ASN1_OBJECT *a)
{
return OBJ_obj2txt(buf, buf_len, a, 0);
}
int i2a_ASN1_OBJECT(BIO *bp, 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)) {
p = OPENSSL_malloc(i + 1);
if (!p)
return -1;
i2t_ASN1_OBJECT(p, i + 1, a);
}
if (i <= 0)
return BIO_write(bp, "<INVALID>", 9);
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;
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;
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;
if (data != NULL)
OPENSSL_free(data);
data = (unsigned char *)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 ((ret != NULL) && ((a == NULL) || (*a != ret)))
ASN1_OBJECT_free(ret);
return (NULL);
}
ASN1_OBJECT *ASN1_OBJECT_new(void)
{
ASN1_OBJECT *ret;
ret = (ASN1_OBJECT *)OPENSSL_malloc(sizeof(ASN1_OBJECT));
if (ret == NULL) {
ASN1err(ASN1_F_ASN1_OBJECT_NEW, ERR_R_MALLOC_FAILURE);
return (NULL);
}
ret->length = 0;
ret->data = NULL;
ret->nid = 0;
ret->sn = NULL;
ret->ln = 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 */
if (a->sn != NULL)
OPENSSL_free((void *)a->sn);
if (a->ln != NULL)
OPENSSL_free((void *)a->ln);
#endif
a->sn = a->ln = NULL;
}
if (a->flags & ASN1_OBJECT_FLAG_DYNAMIC_DATA) {
if (a->data != NULL)
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));
}
IMPLEMENT_STACK_OF(ASN1_OBJECT)
IMPLEMENT_ASN1_SET_OF(ASN1_OBJECT)
@@ -0,0 +1,78 @@
/* crypto/asn1/a_octet.c */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.]
*/
#include <stdio.h>
#include "cryptlib.h"
#include <openssl/asn1.h>
ASN1_OCTET_STRING *ASN1_OCTET_STRING_dup(const ASN1_OCTET_STRING *x)
{
return M_ASN1_OCTET_STRING_dup(x);
}
int ASN1_OCTET_STRING_cmp(const ASN1_OCTET_STRING *a,
const ASN1_OCTET_STRING *b)
{
return M_ASN1_OCTET_STRING_cmp(a, b);
}
int ASN1_OCTET_STRING_set(ASN1_OCTET_STRING *x, const unsigned char *d,
int len)
{
return M_ASN1_OCTET_STRING_set(x, d, len);
}
@@ -0,0 +1,129 @@
/* crypto/asn1/a_print.c */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.]
*/
#include <stdio.h>
#include "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++);
#ifndef CHARSET_EBCDIC
if (!(((c >= 'a') && (c <= 'z')) ||
((c >= 'A') && (c <= 'Z')) ||
(c == ' ') ||
((c >= '0') && (c <= '9')) ||
(c == ' ') || (c == '\'') ||
(c == '(') || (c == ')') ||
(c == '+') || (c == ',') ||
(c == '-') || (c == '.') ||
(c == '/') || (c == ':') || (c == '=') || (c == '?')))
ia5 = 1;
if (c & 0x80)
t61 = 1;
#else
if (!isalnum(c) && (c != ' ') && strchr("'()+,-./:=?", c) == NULL)
ia5 = 1;
if (os_toascii[c] & 0x80)
t61 = 1;
#endif
}
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);
}
@@ -0,0 +1,243 @@
/* crypto/asn1/a_set.c */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.]
*/
#include <stdio.h>
#include <limits.h>
#include "cryptlib.h"
#include <openssl/asn1_mac.h>
#ifndef NO_ASN1_OLD
typedef struct {
unsigned char *pbData;
int cbData;
} MYBLOB;
/*
* SetBlobCmp This function compares two elements of SET_OF block
*/
static int SetBlobCmp(const void *elem1, const void *elem2)
{
const MYBLOB *b1 = (const MYBLOB *)elem1;
const MYBLOB *b2 = (const MYBLOB *)elem2;
int r;
r = memcmp(b1->pbData, b2->pbData,
b1->cbData < b2->cbData ? b1->cbData : b2->cbData);
if (r != 0)
return r;
return b1->cbData - b2->cbData;
}
/*
* int is_set: if TRUE, then sort the contents (i.e. it isn't a SEQUENCE)
*/
int i2d_ASN1_SET(STACK_OF(OPENSSL_BLOCK) *a, unsigned char **pp,
i2d_of_void *i2d, int ex_tag, int ex_class, int is_set)
{
int ret = 0, r;
int i;
unsigned char *p;
unsigned char *pStart, *pTempMem;
MYBLOB *rgSetBlob;
int totSize;
if (a == NULL)
return (0);
for (i = sk_OPENSSL_BLOCK_num(a) - 1; i >= 0; i--) {
int tmplen = i2d(sk_OPENSSL_BLOCK_value(a, i), NULL);
if (tmplen > INT_MAX - ret)
return -1;
ret += i2d(sk_OPENSSL_BLOCK_value(a, i), NULL);
}
r = ASN1_object_size(1, ret, ex_tag);
if (pp == NULL || r == -1)
return (r);
p = *pp;
ASN1_put_object(&p, 1, ret, ex_tag, ex_class);
/* Modified by gp@nsj.co.jp */
/* And then again by Ben */
/* And again by Steve */
if (!is_set || (sk_OPENSSL_BLOCK_num(a) < 2)) {
for (i = 0; i < sk_OPENSSL_BLOCK_num(a); i++)
i2d(sk_OPENSSL_BLOCK_value(a, i), &p);
*pp = p;
return (r);
}
pStart = p; /* Catch the beg of Setblobs */
/* In this array we will store the SET blobs */
rgSetBlob = OPENSSL_malloc(sk_OPENSSL_BLOCK_num(a) * sizeof(MYBLOB));
if (rgSetBlob == NULL) {
ASN1err(ASN1_F_I2D_ASN1_SET, ERR_R_MALLOC_FAILURE);
return (0);
}
for (i = 0; i < sk_OPENSSL_BLOCK_num(a); i++) {
rgSetBlob[i].pbData = p; /* catch each set encode blob */
i2d(sk_OPENSSL_BLOCK_value(a, i), &p);
rgSetBlob[i].cbData = p - rgSetBlob[i].pbData; /* Length of this
* SetBlob */
}
*pp = p;
totSize = p - pStart; /* This is the total size of all set blobs */
/*
* Now we have to sort the blobs. I am using a simple algo. *Sort ptrs
* *Copy to temp-mem *Copy from temp-mem to user-mem
*/
qsort(rgSetBlob, sk_OPENSSL_BLOCK_num(a), sizeof(MYBLOB), SetBlobCmp);
if (!(pTempMem = OPENSSL_malloc(totSize))) {
ASN1err(ASN1_F_I2D_ASN1_SET, ERR_R_MALLOC_FAILURE);
return (0);
}
/* Copy to temp mem */
p = pTempMem;
for (i = 0; i < sk_OPENSSL_BLOCK_num(a); ++i) {
memcpy(p, rgSetBlob[i].pbData, rgSetBlob[i].cbData);
p += rgSetBlob[i].cbData;
}
/* Copy back to user mem*/
memcpy(pStart, pTempMem, totSize);
OPENSSL_free(pTempMem);
OPENSSL_free(rgSetBlob);
return (r);
}
STACK_OF(OPENSSL_BLOCK) *d2i_ASN1_SET(STACK_OF(OPENSSL_BLOCK) **a,
const unsigned char **pp,
long length, d2i_of_void *d2i,
void (*free_func) (OPENSSL_BLOCK),
int ex_tag, int ex_class)
{
ASN1_const_CTX c;
STACK_OF(OPENSSL_BLOCK) *ret = NULL;
if ((a == NULL) || ((*a) == NULL)) {
if ((ret = sk_OPENSSL_BLOCK_new_null()) == NULL) {
ASN1err(ASN1_F_D2I_ASN1_SET, ERR_R_MALLOC_FAILURE);
goto err;
}
} else
ret = (*a);
c.p = *pp;
c.max = (length == 0) ? 0 : (c.p + length);
c.inf = ASN1_get_object(&c.p, &c.slen, &c.tag, &c.xclass, c.max - c.p);
if (c.inf & 0x80)
goto err;
if (ex_class != c.xclass) {
ASN1err(ASN1_F_D2I_ASN1_SET, ASN1_R_BAD_CLASS);
goto err;
}
if (ex_tag != c.tag) {
ASN1err(ASN1_F_D2I_ASN1_SET, ASN1_R_BAD_TAG);
goto err;
}
if ((c.slen + c.p) > c.max) {
ASN1err(ASN1_F_D2I_ASN1_SET, ASN1_R_LENGTH_ERROR);
goto err;
}
/*
* check for infinite constructed - it can be as long as the amount of
* data passed to us
*/
if (c.inf == (V_ASN1_CONSTRUCTED + 1))
c.slen = length + *pp - c.p;
c.max = c.p + c.slen;
while (c.p < c.max) {
char *s;
if (M_ASN1_D2I_end_sequence())
break;
/*
* XXX: This was called with 4 arguments, incorrectly, it seems if
* ((s=func(NULL,&c.p,c.slen,c.max-c.p)) == NULL)
*/
if ((s = d2i(NULL, &c.p, c.slen)) == NULL) {
ASN1err(ASN1_F_D2I_ASN1_SET, ASN1_R_ERROR_PARSING_SET_ELEMENT);
asn1_add_error(*pp, (int)(c.p - *pp));
goto err;
}
if (!sk_OPENSSL_BLOCK_push(ret, s))
goto err;
}
if (a != NULL)
(*a) = ret;
*pp = c.p;
return (ret);
err:
if ((ret != NULL) && ((a == NULL) || (*a != ret))) {
if (free_func != NULL)
sk_OPENSSL_BLOCK_pop_free(ret, free_func);
else
sk_OPENSSL_BLOCK_free(ret);
}
return (NULL);
}
#endif
@@ -0,0 +1,331 @@
/* crypto/asn1/a_sign.c */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.]
*/
/* ====================================================================
* Copyright (c) 1998-2003 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
* openssl-core@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 <time.h>
#include "cryptlib.h"
#ifndef NO_SYS_TYPES_H
# include <sys/types.h>
#endif
#include <openssl/bn.h>
#include <openssl/evp.h>
#include <openssl/x509.h>
#include <openssl/objects.h>
#include <openssl/buffer.h>
#include "asn1_locl.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;
unsigned char *p, *buf_in = NULL, *buf_out = NULL;
int i, inl = 0, outl = 0, outll = 0;
X509_ALGOR *a;
EVP_MD_CTX_init(&ctx);
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 = (unsigned char *)OPENSSL_malloc((unsigned int)inl);
outll = outl = EVP_PKEY_size(pkey);
buf_out = (unsigned char *)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;
}
if (signature->data != NULL)
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_cleanup(&ctx);
if (buf_in != NULL) {
OPENSSL_cleanse((char *)buf_in, (unsigned int)inl);
OPENSSL_free(buf_in);
}
if (buf_out != NULL) {
OPENSSL_cleanse((char *)buf_out, outll);
OPENSSL_free(buf_out);
}
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)
{
EVP_MD_CTX ctx;
EVP_MD_CTX_init(&ctx);
if (!EVP_DigestSignInit(&ctx, NULL, type, NULL, pkey)) {
EVP_MD_CTX_cleanup(&ctx);
return 0;
}
return ASN1_item_sign_ctx(it, algor1, algor2, signature, asn, &ctx);
}
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(ctx->pctx);
if (!type || !pkey) {
ASN1err(ASN1_F_ASN1_ITEM_SIGN_CTX, ASN1_R_CONTEXT_NOT_INITIALISED);
return 0;
}
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->flags & EVP_MD_FLAG_PKEY_METHOD_SIGNATURE) {
if (!pkey->ameth ||
!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);
return 0;
}
} else
signid = type->pkey_type;
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_DigestSignUpdate(ctx, buf_in, inl)
|| !EVP_DigestSignFinal(ctx, buf_out, &outl)) {
outl = 0;
ASN1err(ASN1_F_ASN1_ITEM_SIGN_CTX, ERR_R_EVP_LIB);
goto err;
}
if (signature->data != NULL)
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_cleanup(ctx);
if (buf_in != NULL) {
OPENSSL_cleanse((char *)buf_in, (unsigned int)inl);
OPENSSL_free(buf_in);
}
if (buf_out != NULL) {
OPENSSL_cleanse((char *)buf_out, outll);
OPENSSL_free(buf_out);
}
return (outl);
}
@@ -0,0 +1,670 @@
/* a_strex.c */
/*
* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
* 2000.
*/
/* ====================================================================
* Copyright (c) 2000-2018 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 <string.h>
#include "cryptlib.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_QUOTE | \
ASN1_STRFLGS_ESC_CTRL | \
ASN1_STRFLGS_ESC_MSB)
/*
* Three IO functions for sending data to memory, a BIO and and a FILE
* pointer.
*/
#if 0 /* never used */
static int send_mem_chars(void *arg, const void *buf, int len)
{
unsigned char **out = arg;
if (!out)
return 1;
memcpy(*out, buf, len);
*out += len;
return 1;
}
#endif
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;
}
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;
}
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 char flags, char *do_quotes,
char_io *io_ch, void *arg)
{
unsigned char chflgs, 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)) {
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 char flags, char *quotes, char_io *io_ch,
void *arg)
{
int i, outlen, len, charwidth;
unsigned char orflags, *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], (unsigned char)(flags | orflags),
quotes, io_ch, arg);
if (len < 0)
return -1;
outlen += len;
}
} else {
len =
do_esc_char(c, (unsigned char)(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,
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);
der_buf = OPENSSL_malloc(der_len);
if (!der_buf)
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, 0, -1, /* 10-13 */
-1, -1, -1, -1, /* 15-17 */
1, 1, 1, /* 18-20 */
-1, 1, 1, 1, /* 21-24 */
-1, 1, -1, /* 25-27 */
4, -1, 2 /* 28-30 */
};
/*
* 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,
ASN1_STRING *str)
{
int outlen, len;
int type;
char quotes;
unsigned char flags;
quotes = 0;
/* Keep a copy of escape flags */
flags = (unsigned char)(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, &quotes, 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, X509_NAME *n,
int indent, unsigned long flags)
{
int i, prev = -1, orflags, cnt;
int fn_opt, fn_nid;
ASN1_OBJECT *fn;
ASN1_STRING *val;
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 == ent->set) {
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 = ent->set;
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, 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_FP_API
int X509_NAME_print_ex_fp(FILE *fp, 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, ASN1_STRING *str, unsigned long flags)
{
return do_print_ex(send_bio_chars, out, flags, str);
}
#ifndef OPENSSL_NO_FP_API
int ASN1_STRING_print_ex_fp(FILE *fp, 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, 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;
}
@@ -0,0 +1,315 @@
/* a_strnid.c */
/*
* Written by Dr Stephen N Henson (steve@openssl.org) 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 <ctype.h>
#include "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)) {
if (!p[5])
return 0;
mask = strtoul(p + 5, &end, 0);
if (*end)
return 0;
} else if (!strcmp(p, "nombstr"))
mask = ~((unsigned long)(B_ASN1_BMPSTRING | B_ASN1_UTF8STRING));
else if (!strcmp(p, "pkix"))
mask = ~((unsigned long)B_ASN1_T61STRING);
else if (!strcmp(p, "utf8only"))
mask = B_ASN1_UTF8STRING;
else if (!strcmp(p, "default"))
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)
out = &str;
tbl = ASN1_STRING_TABLE_get(nid);
if (tbl) {
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:
*/
/* 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
/* 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_jurisdictionCountryName, 2, 2, B_ASN1_PRINTABLESTRING, STABLE_NO_MASK}
};
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 *ttmp;
ASN1_STRING_TABLE fnd;
fnd.nid = nid;
ttmp = OBJ_bsearch_table(&fnd, tbl_standard,
sizeof(tbl_standard) /
sizeof(ASN1_STRING_TABLE));
if (ttmp)
return ttmp;
if (!stable)
return NULL;
idx = sk_ASN1_STRING_TABLE_find(stable, &fnd);
if (idx < 0)
return NULL;
return sk_ASN1_STRING_TABLE_value(stable, idx);
}
int ASN1_STRING_TABLE_add(int nid,
long minsize, long maxsize, unsigned long mask,
unsigned long flags)
{
ASN1_STRING_TABLE *tmp;
char new_nid = 0;
flags &= ~STABLE_FLAGS_MALLOC;
if (!stable)
stable = sk_ASN1_STRING_TABLE_new(sk_table_cmp);
if (!stable) {
ASN1err(ASN1_F_ASN1_STRING_TABLE_ADD, ERR_R_MALLOC_FAILURE);
return 0;
}
if (!(tmp = ASN1_STRING_TABLE_get(nid))) {
tmp = OPENSSL_malloc(sizeof(ASN1_STRING_TABLE));
if (!tmp) {
ASN1err(ASN1_F_ASN1_STRING_TABLE_ADD, ERR_R_MALLOC_FAILURE);
return 0;
}
tmp->flags = flags | STABLE_FLAGS_MALLOC;
tmp->nid = nid;
tmp->minsize = tmp->maxsize = -1;
new_nid = 1;
} else
tmp->flags = (tmp->flags & STABLE_FLAGS_MALLOC) | flags;
if (minsize != -1)
tmp->minsize = minsize;
if (maxsize != -1)
tmp->maxsize = maxsize;
tmp->mask = mask;
if (new_nid)
sk_ASN1_STRING_TABLE_push(stable, tmp);
return 1;
}
void ASN1_STRING_TABLE_cleanup(void)
{
STACK_OF(ASN1_STRING_TABLE) *tmp;
tmp = stable;
if (!tmp)
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);
}
IMPLEMENT_STACK_OF(ASN1_STRING_TABLE)
#ifdef STRING_TABLE_TEST
main()
{
ASN1_STRING_TABLE *tmp;
int i, last_nid = -1;
for (tmp = tbl_standard, i = 0;
i < sizeof(tbl_standard) / sizeof(ASN1_STRING_TABLE); i++, tmp++) {
if (tmp->nid < last_nid) {
last_nid = 0;
break;
}
last_nid = tmp->nid;
}
if (last_nid != 0) {
printf("Table order OK\n");
exit(0);
}
for (tmp = tbl_standard, i = 0;
i < sizeof(tbl_standard) / sizeof(ASN1_STRING_TABLE); i++, tmp++)
printf("Index %d, NID %d, Name=%s\n", i, tmp->nid,
OBJ_nid2ln(tmp->nid));
}
#endif
@@ -0,0 +1,236 @@
/* crypto/asn1/a_time.c */
/* ====================================================================
* 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).
*
*/
/*-
* This is an implementation of the ASN1 Time structure which is:
* Time ::= CHOICE {
* utcTime UTCTime,
* generalTime GeneralizedTime }
* written by Steve Henson.
*/
#include <stdio.h>
#include <time.h>
#include "cryptlib.h"
#include "o_time.h"
#include <openssl/asn1t.h>
#include "asn1_locl.h"
IMPLEMENT_ASN1_MSTRING(ASN1_TIME, B_ASN1_TIME)
IMPLEMENT_ASN1_FUNCTIONS(ASN1_TIME)
#if 0
int i2d_ASN1_TIME(ASN1_TIME *a, unsigned char **pp)
{
# ifdef CHARSET_EBCDIC
/* KLUDGE! We convert to ascii before writing DER */
char tmp[24];
ASN1_STRING tmpstr;
if (a->type == V_ASN1_UTCTIME || a->type == V_ASN1_GENERALIZEDTIME) {
int len;
tmpstr = *(ASN1_STRING *)a;
len = tmpstr.length;
ebcdic2ascii(tmp, tmpstr.data,
(len >= sizeof(tmp)) ? sizeof(tmp) : len);
tmpstr.data = tmp;
a = (ASN1_GENERALIZEDTIME *)&tmpstr;
}
# endif
if (a->type == V_ASN1_UTCTIME || a->type == V_ASN1_GENERALIZEDTIME)
return (i2d_ASN1_bytes((ASN1_STRING *)a, pp,
a->type, V_ASN1_UNIVERSAL));
ASN1err(ASN1_F_I2D_ASN1_TIME, ASN1_R_EXPECTING_A_TIME);
return -1;
}
#endif
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;
}
if ((ts->tm_year >= 50) && (ts->tm_year < 150))
return ASN1_UTCTIME_adj(s, t, offset_day, offset_sec);
return ASN1_GENERALIZEDTIME_adj(s, t, offset_day, offset_sec);
}
int ASN1_TIME_check(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(ASN1_TIME *t,
ASN1_GENERALIZEDTIME **out)
{
ASN1_GENERALIZEDTIME *ret = NULL;
char *str;
int newlen;
if (!ASN1_TIME_check(t))
return NULL;
if (!out || !*out) {
if (!(ret = ASN1_GENERALIZEDTIME_new()))
goto err;
} else {
ret = *out;
}
/* If already GeneralizedTime just copy across */
if (t->type == V_ASN1_GENERALIZEDTIME) {
if (!ASN1_STRING_set(ret, t->data, t->length))
goto err;
goto done;
}
/* grow the string */
if (!ASN1_STRING_set(ret, NULL, t->length + 2))
goto err;
/* ASN1_STRING_set() allocated 'len + 1' bytes. */
newlen = t->length + 2 + 1;
str = (char *)ret->data;
/* Work out the century and prepend */
if (t->data[0] >= '5')
BUF_strlcpy(str, "19", newlen);
else
BUF_strlcpy(str, "20", newlen);
BUF_strlcat(str, (char *)t->data, newlen);
done:
if (out != NULL && *out == NULL)
*out = ret;
return ret;
err:
if (out == NULL || *out != ret)
ASN1_GENERALIZEDTIME_free(ret);
return NULL;
}
int ASN1_TIME_set_string(ASN1_TIME *s, const char *str)
{
ASN1_TIME t;
t.length = strlen(str);
t.data = (unsigned char *)str;
t.flags = 0;
t.type = V_ASN1_UTCTIME;
if (!ASN1_TIME_check(&t)) {
t.type = V_ASN1_GENERALIZEDTIME;
if (!ASN1_TIME_check(&t))
return 0;
}
if (s && !ASN1_STRING_copy((ASN1_STRING *)s, (ASN1_STRING *)&t))
return 0;
return 1;
}
static int asn1_time_to_tm(struct tm *tm, const ASN1_TIME *t)
{
if (t == NULL) {
time_t now_t;
time(&now_t);
if (OPENSSL_gmtime(&now_t, tm))
return 1;
return 0;
}
if (t->type == V_ASN1_UTCTIME)
return asn1_utctime_to_tm(tm, t);
else if (t->type == V_ASN1_GENERALIZEDTIME)
return asn1_generalizedtime_to_tm(tm, t);
return 0;
}
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(&tm_from, from))
return 0;
if (!asn1_time_to_tm(&tm_to, to))
return 0;
return OPENSSL_gmtime_diff(pday, psec, &tm_from, &tm_to);
}
@@ -0,0 +1,155 @@
/* crypto/asn1/a_type.c */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.]
*/
#include <stdio.h>
#include "cryptlib.h"
#include <openssl/asn1t.h>
#include <openssl/objects.h>
int ASN1_TYPE_get(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);
}
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;
}
IMPLEMENT_STACK_OF(ASN1_TYPE)
IMPLEMENT_ASN1_SET_OF(ASN1_TYPE)
/* 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;
}
@@ -0,0 +1,352 @@
/* crypto/asn1/a_utctm.c */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.]
*/
#include <stdio.h>
#include <time.h>
#include "cryptlib.h"
#include "o_time.h"
#include <openssl/asn1.h>
#include "asn1_locl.h"
#if 0
int i2d_ASN1_UTCTIME(ASN1_UTCTIME *a, unsigned char **pp)
{
# ifndef CHARSET_EBCDIC
return (i2d_ASN1_bytes((ASN1_STRING *)a, pp,
V_ASN1_UTCTIME, V_ASN1_UNIVERSAL));
# else
/* KLUDGE! We convert to ascii before writing DER */
int len;
char tmp[24];
ASN1_STRING x = *(ASN1_STRING *)a;
len = x.length;
ebcdic2ascii(tmp, x.data, (len >= sizeof(tmp)) ? sizeof(tmp) : len);
x.data = tmp;
return i2d_ASN1_bytes(&x, pp, V_ASN1_UTCTIME, V_ASN1_UNIVERSAL);
# endif
}
ASN1_UTCTIME *d2i_ASN1_UTCTIME(ASN1_UTCTIME **a, unsigned char **pp,
long length)
{
ASN1_UTCTIME *ret = NULL;
ret = (ASN1_UTCTIME *)d2i_ASN1_bytes((ASN1_STRING **)a, pp, length,
V_ASN1_UTCTIME, V_ASN1_UNIVERSAL);
if (ret == NULL) {
ASN1err(ASN1_F_D2I_ASN1_UTCTIME, ERR_R_NESTED_ASN1_ERROR);
return (NULL);
}
# ifdef CHARSET_EBCDIC
ascii2ebcdic(ret->data, ret->data, ret->length);
# endif
if (!ASN1_UTCTIME_check(ret)) {
ASN1err(ASN1_F_D2I_ASN1_UTCTIME, ASN1_R_INVALID_TIME_FORMAT);
goto err;
}
return (ret);
err:
if ((ret != NULL) && ((a == NULL) || (*a != ret)))
M_ASN1_UTCTIME_free(ret);
return (NULL);
}
#endif
int asn1_utctime_to_tm(struct tm *tm, const ASN1_UTCTIME *d)
{
static const int min[8] = { 0, 1, 1, 0, 0, 0, 0, 0 };
static const int max[8] = { 99, 12, 31, 23, 59, 59, 12, 59 };
char *a;
int n, i, l, o;
if (d->type != V_ASN1_UTCTIME)
return (0);
l = d->length;
a = (char *)d->data;
o = 0;
if (l < 11)
goto err;
for (i = 0; i < 6; i++) {
if ((i == 5) && ((a[o] == 'Z') || (a[o] == '+') || (a[o] == '-'))) {
i++;
if (tm)
tm->tm_sec = 0;
break;
}
if ((a[o] < '0') || (a[o] > '9'))
goto err;
n = a[o] - '0';
if (++o > l)
goto err;
if ((a[o] < '0') || (a[o] > '9'))
goto err;
n = (n * 10) + a[o] - '0';
if (++o > l)
goto err;
if ((n < min[i]) || (n > max[i]))
goto err;
if (tm) {
switch (i) {
case 0:
tm->tm_year = n < 50 ? n + 100 : n;
break;
case 1:
tm->tm_mon = n - 1;
break;
case 2:
tm->tm_mday = n;
break;
case 3:
tm->tm_hour = n;
break;
case 4:
tm->tm_min = n;
break;
case 5:
tm->tm_sec = n;
break;
}
}
}
if (a[o] == 'Z')
o++;
else if ((a[o] == '+') || (a[o] == '-')) {
int offsign = a[o] == '-' ? 1 : -1, offset = 0;
o++;
if (o + 4 > l)
goto err;
for (i = 6; i < 8; i++) {
if ((a[o] < '0') || (a[o] > '9'))
goto err;
n = a[o] - '0';
o++;
if ((a[o] < '0') || (a[o] > '9'))
goto err;
n = (n * 10) + a[o] - '0';
if ((n < min[i]) || (n > max[i]))
goto err;
if (tm) {
if (i == 6)
offset = n * 3600;
else if (i == 7)
offset += n * 60;
}
o++;
}
if (offset && !OPENSSL_gmtime_adj(tm, 0, offset * offsign))
return 0;
}
return o == l;
err:
return 0;
}
int ASN1_UTCTIME_check(const ASN1_UTCTIME *d)
{
return asn1_utctime_to_tm(NULL, d);
}
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;
if (ASN1_UTCTIME_check(&t)) {
if (s != NULL) {
if (!ASN1_STRING_set((ASN1_STRING *)s,
(unsigned char *)str, t.length))
return 0;
s->type = V_ASN1_UTCTIME;
}
return (1);
} else
return (0);
}
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)
{
char *p;
struct tm *ts;
struct tm data;
size_t len = 20;
int free_s = 0;
if (s == NULL) {
free_s = 1;
s = M_ASN1_UTCTIME_new();
}
if (s == NULL)
goto err;
ts = OPENSSL_gmtime(&t, &data);
if (ts == NULL)
goto err;
if (offset_day || offset_sec) {
if (!OPENSSL_gmtime_adj(ts, offset_day, offset_sec))
goto err;
}
if ((ts->tm_year < 50) || (ts->tm_year >= 150))
goto err;
p = (char *)s->data;
if ((p == NULL) || ((size_t)s->length < len)) {
p = OPENSSL_malloc(len);
if (p == NULL) {
ASN1err(ASN1_F_ASN1_UTCTIME_ADJ, ERR_R_MALLOC_FAILURE);
goto err;
}
if (s->data != NULL)
OPENSSL_free(s->data);
s->data = (unsigned char *)p;
}
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);
s->length = strlen(p);
s->type = V_ASN1_UTCTIME;
#ifdef CHARSET_EBCDIC_not
ebcdic2ascii(s->data, s->data, s->length);
#endif
return (s);
err:
if (free_s && s)
M_ASN1_UTCTIME_free(s);
return NULL;
}
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))
return -2;
if (!OPENSSL_gmtime_diff(&day, &sec, &ttm, &stm))
return -2;
if (day > 0)
return 1;
if (day < 0)
return -1;
if (sec > 0)
return 1;
if (sec < 0)
return -1;
return 0;
}
#if 0
time_t ASN1_UTCTIME_get(const ASN1_UTCTIME *s)
{
struct tm tm;
int offset;
memset(&tm, '\0', sizeof(tm));
# define g2(p) (((p)[0]-'0')*10+(p)[1]-'0')
tm.tm_year = g2(s->data);
if (tm.tm_year < 50)
tm.tm_year += 100;
tm.tm_mon = g2(s->data + 2) - 1;
tm.tm_mday = g2(s->data + 4);
tm.tm_hour = g2(s->data + 6);
tm.tm_min = g2(s->data + 8);
tm.tm_sec = g2(s->data + 10);
if (s->data[12] == 'Z')
offset = 0;
else {
offset = g2(s->data + 13) * 60 + g2(s->data + 15);
if (s->data[12] == '-')
offset = -offset;
}
# undef g2
/*
* FIXME: mktime assumes the current timezone
* instead of UTC, and unless we rewrite OpenSSL
* in Lisp we cannot locally change the timezone
* without possibly interfering with other parts
* of the program. timegm, which uses UTC, is
* non-standard.
* Also time_t is inappropriate for general
* UTC times because it may a 32 bit type.
*/
return mktime(&tm) - offset * 60;
}
#endif
@@ -0,0 +1,237 @@
/* crypto/asn1/a_utf8.c */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.]
*/
#include <stdio.h>
#include "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;
}
@@ -0,0 +1,231 @@
/* crypto/asn1/a_verify.c */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.]
*/
#include <stdio.h>
#include <time.h>
#include "cryptlib.h"
#include "asn1_locl.h"
#ifndef NO_SYS_TYPES_H
# include <sys/types.h>
#endif
#include <openssl/bn.h>
#include <openssl/x509.h>
#include <openssl/objects.h>
#include <openssl/buffer.h>
#include <openssl/evp.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;
const EVP_MD *type;
unsigned char *p, *buf_in = NULL;
int ret = -1, i, inl;
EVP_MD_CTX_init(&ctx);
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);
if (!EVP_VerifyInit_ex(&ctx, type, NULL)
|| !EVP_VerifyUpdate(&ctx, (unsigned char *)buf_in, inl)) {
ASN1err(ASN1_F_ASN1_VERIFY, ERR_R_EVP_LIB);
ret = 0;
goto err;
}
OPENSSL_cleanse(buf_in, (unsigned int)inl);
OPENSSL_free(buf_in);
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;
}
/*
* we don't need to zero the 'ctx' because we just checked public
* information
*/
/* memset(&ctx,0,sizeof(ctx)); */
ret = 1;
err:
EVP_MD_CTX_cleanup(&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;
unsigned char *buf_in = NULL;
int ret = -1, inl;
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;
}
EVP_MD_CTX_init(&ctx);
/* 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;
}
if (!EVP_DigestVerifyUpdate(&ctx, buf_in, inl)) {
ASN1err(ASN1_F_ASN1_ITEM_VERIFY, ERR_R_EVP_LIB);
ret = 0;
goto err;
}
OPENSSL_cleanse(buf_in, (unsigned int)inl);
OPENSSL_free(buf_in);
if (EVP_DigestVerifyFinal(&ctx, signature->data,
(size_t)signature->length) <= 0) {
ASN1err(ASN1_F_ASN1_ITEM_VERIFY, ERR_R_EVP_LIB);
ret = 0;
goto err;
}
/*
* we don't need to zero the 'ctx' because we just checked public
* information
*/
/* memset(&ctx,0,sizeof(ctx)); */
ret = 1;
err:
EVP_MD_CTX_cleanup(&ctx);
return (ret);
}
@@ -0,0 +1,501 @@
/*
* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
* 2006.
*/
/* ====================================================================
* Copyright (c) 2006-2018 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/asn1t.h>
#include <openssl/x509.h>
#ifndef OPENSSL_NO_ENGINE
# include <openssl/engine.h>
#endif
#include "asn1_locl.h"
extern const EVP_PKEY_ASN1_METHOD rsa_asn1_meths[];
extern const EVP_PKEY_ASN1_METHOD dsa_asn1_meths[];
extern const EVP_PKEY_ASN1_METHOD dh_asn1_meth;
extern const EVP_PKEY_ASN1_METHOD dhx_asn1_meth;
extern const EVP_PKEY_ASN1_METHOD eckey_asn1_meth;
extern const EVP_PKEY_ASN1_METHOD hmac_asn1_meth;
extern const EVP_PKEY_ASN1_METHOD cmac_asn1_meth;
/* Keep this sorted in type order !! */
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_DH
&dhx_asn1_meth
#endif
};
typedef int sk_cmp_fn_type(const char *const *a, const char *const *b);
DECLARE_STACK_OF(EVP_PKEY_ASN1_METHOD)
static STACK_OF(EVP_PKEY_ASN1_METHOD) *app_methods = NULL;
#ifdef TEST
void main()
{
int i;
for (i = 0;
i < sizeof(standard_methods) / sizeof(EVP_PKEY_ASN1_METHOD *); i++)
fprintf(stderr, "Number %d id=%d (%s)\n", i,
standard_methods[i]->pkey_id,
OBJ_nid2sn(standard_methods[i]->pkey_id));
}
#endif
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 = sizeof(standard_methods) / sizeof(EVP_PKEY_ASN1_METHOD *);
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 = sizeof(standard_methods) / sizeof(EVP_PKEY_ASN1_METHOD *);
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, sizeof(standard_methods)
/ sizeof(EVP_PKEY_ASN1_METHOD *));
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;
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 = 0; i < EVP_PKEY_asn1_get_count(); i++) {
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))
return ameth;
}
return NULL;
}
int EVP_PKEY_asn1_add0(const EVP_PKEY_ASN1_METHOD *ameth)
{
/*
* 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 (!((ameth->pem_str == NULL
&& (ameth->pkey_flags & ASN1_PKEY_ALIAS) != 0)
|| (ameth->pem_str != NULL
&& (ameth->pkey_flags & ASN1_PKEY_ALIAS) == 0))) {
return 0;
}
if (app_methods == NULL) {
app_methods = sk_EVP_PKEY_ASN1_METHOD_new(ameth_cmp);
if (!app_methods)
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)
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(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;
ameth = OPENSSL_malloc(sizeof(EVP_PKEY_ASN1_METHOD));
if (!ameth)
return NULL;
memset(ameth, 0, sizeof(EVP_PKEY_ASN1_METHOD));
ameth->pkey_id = id;
ameth->pkey_base_id = id;
ameth->pkey_flags = flags | ASN1_PKEY_DYNAMIC;
if (info) {
ameth->info = BUF_strdup(info);
if (!ameth->info)
goto err;
} else
ameth->info = NULL;
if (pem_str) {
ameth->pem_str = BUF_strdup(pem_str);
if (!ameth->pem_str)
goto err;
} else
ameth->pem_str = NULL;
ameth->pub_decode = 0;
ameth->pub_encode = 0;
ameth->pub_cmp = 0;
ameth->pub_print = 0;
ameth->priv_decode = 0;
ameth->priv_encode = 0;
ameth->priv_print = 0;
ameth->old_priv_encode = 0;
ameth->old_priv_decode = 0;
ameth->item_verify = 0;
ameth->item_sign = 0;
ameth->pkey_size = 0;
ameth->pkey_bits = 0;
ameth->param_decode = 0;
ameth->param_encode = 0;
ameth->param_missing = 0;
ameth->param_copy = 0;
ameth->param_cmp = 0;
ameth->param_print = 0;
ameth->pkey_free = 0;
ameth->pkey_ctrl = 0;
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;
}
void EVP_PKEY_asn1_free(EVP_PKEY_ASN1_METHOD *ameth)
{
if (ameth && (ameth->pkey_flags & ASN1_PKEY_DYNAMIC)) {
if (ameth->pem_str)
OPENSSL_free(ameth->pem_str);
if (ameth->info)
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,
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_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;
}
@@ -0,0 +1,360 @@
/* crypto/asn1/asn1_err.c */
/* ====================================================================
* Copyright (c) 1999-2020 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
* openssl-core@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).
*
*/
/*
* NOTE: this file was auto generated by the mkerr.pl script: any changes
* made to it will be overwritten when the script next updates this file,
* only reason strings will be preserved.
*/
#include <stdio.h>
#include <openssl/err.h>
#include <openssl/asn1.h>
/* BEGIN ERROR CODES */
#ifndef OPENSSL_NO_ERR
# define ERR_FUNC(func) ERR_PACK(ERR_LIB_ASN1,func,0)
# define ERR_REASON(reason) ERR_PACK(ERR_LIB_ASN1,0,reason)
static ERR_STRING_DATA ASN1_str_functs[] = {
{ERR_FUNC(ASN1_F_A2D_ASN1_OBJECT), "a2d_ASN1_OBJECT"},
{ERR_FUNC(ASN1_F_A2I_ASN1_ENUMERATED), "a2i_ASN1_ENUMERATED"},
{ERR_FUNC(ASN1_F_A2I_ASN1_INTEGER), "a2i_ASN1_INTEGER"},
{ERR_FUNC(ASN1_F_A2I_ASN1_STRING), "a2i_ASN1_STRING"},
{ERR_FUNC(ASN1_F_APPEND_EXP), "APPEND_EXP"},
{ERR_FUNC(ASN1_F_ASN1_BIT_STRING_SET_BIT), "ASN1_BIT_STRING_set_bit"},
{ERR_FUNC(ASN1_F_ASN1_CB), "ASN1_CB"},
{ERR_FUNC(ASN1_F_ASN1_CHECK_TLEN), "ASN1_CHECK_TLEN"},
{ERR_FUNC(ASN1_F_ASN1_COLLATE_PRIMITIVE), "ASN1_COLLATE_PRIMITIVE"},
{ERR_FUNC(ASN1_F_ASN1_COLLECT), "ASN1_COLLECT"},
{ERR_FUNC(ASN1_F_ASN1_D2I_EX_PRIMITIVE), "ASN1_D2I_EX_PRIMITIVE"},
{ERR_FUNC(ASN1_F_ASN1_D2I_FP), "ASN1_d2i_fp"},
{ERR_FUNC(ASN1_F_ASN1_D2I_READ_BIO), "ASN1_D2I_READ_BIO"},
{ERR_FUNC(ASN1_F_ASN1_DIGEST), "ASN1_digest"},
{ERR_FUNC(ASN1_F_ASN1_DO_ADB), "ASN1_DO_ADB"},
{ERR_FUNC(ASN1_F_ASN1_DUP), "ASN1_dup"},
{ERR_FUNC(ASN1_F_ASN1_ENUMERATED_SET), "ASN1_ENUMERATED_set"},
{ERR_FUNC(ASN1_F_ASN1_ENUMERATED_TO_BN), "ASN1_ENUMERATED_to_BN"},
{ERR_FUNC(ASN1_F_ASN1_EX_C2I), "ASN1_EX_C2I"},
{ERR_FUNC(ASN1_F_ASN1_FIND_END), "ASN1_FIND_END"},
{ERR_FUNC(ASN1_F_ASN1_GENERALIZEDTIME_ADJ), "ASN1_GENERALIZEDTIME_adj"},
{ERR_FUNC(ASN1_F_ASN1_GENERALIZEDTIME_SET), "ASN1_GENERALIZEDTIME_set"},
{ERR_FUNC(ASN1_F_ASN1_GENERATE_V3), "ASN1_generate_v3"},
{ERR_FUNC(ASN1_F_ASN1_GET_OBJECT), "ASN1_get_object"},
{ERR_FUNC(ASN1_F_ASN1_HEADER_NEW), "ASN1_HEADER_NEW"},
{ERR_FUNC(ASN1_F_ASN1_I2D_BIO), "ASN1_i2d_bio"},
{ERR_FUNC(ASN1_F_ASN1_I2D_FP), "ASN1_i2d_fp"},
{ERR_FUNC(ASN1_F_ASN1_INTEGER_SET), "ASN1_INTEGER_set"},
{ERR_FUNC(ASN1_F_ASN1_INTEGER_TO_BN), "ASN1_INTEGER_to_BN"},
{ERR_FUNC(ASN1_F_ASN1_ITEM_D2I_FP), "ASN1_item_d2i_fp"},
{ERR_FUNC(ASN1_F_ASN1_ITEM_DUP), "ASN1_item_dup"},
{ERR_FUNC(ASN1_F_ASN1_ITEM_EX_COMBINE_NEW), "ASN1_ITEM_EX_COMBINE_NEW"},
{ERR_FUNC(ASN1_F_ASN1_ITEM_EX_D2I), "ASN1_ITEM_EX_D2I"},
{ERR_FUNC(ASN1_F_ASN1_ITEM_EX_I2D), "ASN1_ITEM_EX_I2D"},
{ERR_FUNC(ASN1_F_ASN1_ITEM_I2D_BIO), "ASN1_item_i2d_bio"},
{ERR_FUNC(ASN1_F_ASN1_ITEM_I2D_FP), "ASN1_item_i2d_fp"},
{ERR_FUNC(ASN1_F_ASN1_ITEM_PACK), "ASN1_item_pack"},
{ERR_FUNC(ASN1_F_ASN1_ITEM_SIGN), "ASN1_item_sign"},
{ERR_FUNC(ASN1_F_ASN1_ITEM_SIGN_CTX), "ASN1_item_sign_ctx"},
{ERR_FUNC(ASN1_F_ASN1_ITEM_UNPACK), "ASN1_item_unpack"},
{ERR_FUNC(ASN1_F_ASN1_ITEM_VERIFY), "ASN1_item_verify"},
{ERR_FUNC(ASN1_F_ASN1_MBSTRING_NCOPY), "ASN1_mbstring_ncopy"},
{ERR_FUNC(ASN1_F_ASN1_OBJECT_NEW), "ASN1_OBJECT_new"},
{ERR_FUNC(ASN1_F_ASN1_OUTPUT_DATA), "ASN1_OUTPUT_DATA"},
{ERR_FUNC(ASN1_F_ASN1_PACK_STRING), "ASN1_pack_string"},
{ERR_FUNC(ASN1_F_ASN1_PCTX_NEW), "ASN1_PCTX_new"},
{ERR_FUNC(ASN1_F_ASN1_PKCS5_PBE_SET), "ASN1_PKCS5_PBE_SET"},
{ERR_FUNC(ASN1_F_ASN1_SEQ_PACK), "ASN1_seq_pack"},
{ERR_FUNC(ASN1_F_ASN1_SEQ_UNPACK), "ASN1_seq_unpack"},
{ERR_FUNC(ASN1_F_ASN1_SIGN), "ASN1_sign"},
{ERR_FUNC(ASN1_F_ASN1_STR2TYPE), "ASN1_STR2TYPE"},
{ERR_FUNC(ASN1_F_ASN1_STRING_SET), "ASN1_STRING_set"},
{ERR_FUNC(ASN1_F_ASN1_STRING_TABLE_ADD), "ASN1_STRING_TABLE_add"},
{ERR_FUNC(ASN1_F_ASN1_STRING_TYPE_NEW), "ASN1_STRING_type_new"},
{ERR_FUNC(ASN1_F_ASN1_TEMPLATE_EX_D2I), "ASN1_TEMPLATE_EX_D2I"},
{ERR_FUNC(ASN1_F_ASN1_TEMPLATE_NEW), "ASN1_TEMPLATE_NEW"},
{ERR_FUNC(ASN1_F_ASN1_TEMPLATE_NOEXP_D2I), "ASN1_TEMPLATE_NOEXP_D2I"},
{ERR_FUNC(ASN1_F_ASN1_TIME_ADJ), "ASN1_TIME_adj"},
{ERR_FUNC(ASN1_F_ASN1_TIME_SET), "ASN1_TIME_set"},
{ERR_FUNC(ASN1_F_ASN1_TYPE_GET_INT_OCTETSTRING),
"ASN1_TYPE_get_int_octetstring"},
{ERR_FUNC(ASN1_F_ASN1_TYPE_GET_OCTETSTRING), "ASN1_TYPE_get_octetstring"},
{ERR_FUNC(ASN1_F_ASN1_UNPACK_STRING), "ASN1_unpack_string"},
{ERR_FUNC(ASN1_F_ASN1_UTCTIME_ADJ), "ASN1_UTCTIME_adj"},
{ERR_FUNC(ASN1_F_ASN1_UTCTIME_SET), "ASN1_UTCTIME_set"},
{ERR_FUNC(ASN1_F_ASN1_VERIFY), "ASN1_verify"},
{ERR_FUNC(ASN1_F_B64_READ_ASN1), "B64_READ_ASN1"},
{ERR_FUNC(ASN1_F_B64_WRITE_ASN1), "B64_WRITE_ASN1"},
{ERR_FUNC(ASN1_F_BIO_NEW_NDEF), "BIO_new_NDEF"},
{ERR_FUNC(ASN1_F_BITSTR_CB), "BITSTR_CB"},
{ERR_FUNC(ASN1_F_BN_TO_ASN1_ENUMERATED), "BN_to_ASN1_ENUMERATED"},
{ERR_FUNC(ASN1_F_BN_TO_ASN1_INTEGER), "BN_to_ASN1_INTEGER"},
{ERR_FUNC(ASN1_F_C2I_ASN1_BIT_STRING), "c2i_ASN1_BIT_STRING"},
{ERR_FUNC(ASN1_F_C2I_ASN1_INTEGER), "c2i_ASN1_INTEGER"},
{ERR_FUNC(ASN1_F_C2I_ASN1_OBJECT), "c2i_ASN1_OBJECT"},
{ERR_FUNC(ASN1_F_COLLECT_DATA), "COLLECT_DATA"},
{ERR_FUNC(ASN1_F_D2I_ASN1_BIT_STRING), "D2I_ASN1_BIT_STRING"},
{ERR_FUNC(ASN1_F_D2I_ASN1_BOOLEAN), "d2i_ASN1_BOOLEAN"},
{ERR_FUNC(ASN1_F_D2I_ASN1_BYTES), "d2i_ASN1_bytes"},
{ERR_FUNC(ASN1_F_D2I_ASN1_GENERALIZEDTIME), "D2I_ASN1_GENERALIZEDTIME"},
{ERR_FUNC(ASN1_F_D2I_ASN1_HEADER), "D2I_ASN1_HEADER"},
{ERR_FUNC(ASN1_F_D2I_ASN1_INTEGER), "D2I_ASN1_INTEGER"},
{ERR_FUNC(ASN1_F_D2I_ASN1_OBJECT), "d2i_ASN1_OBJECT"},
{ERR_FUNC(ASN1_F_D2I_ASN1_SET), "d2i_ASN1_SET"},
{ERR_FUNC(ASN1_F_D2I_ASN1_TYPE_BYTES), "d2i_ASN1_type_bytes"},
{ERR_FUNC(ASN1_F_D2I_ASN1_UINTEGER), "d2i_ASN1_UINTEGER"},
{ERR_FUNC(ASN1_F_D2I_ASN1_UTCTIME), "D2I_ASN1_UTCTIME"},
{ERR_FUNC(ASN1_F_D2I_AUTOPRIVATEKEY), "d2i_AutoPrivateKey"},
{ERR_FUNC(ASN1_F_D2I_NETSCAPE_RSA), "d2i_Netscape_RSA"},
{ERR_FUNC(ASN1_F_D2I_NETSCAPE_RSA_2), "D2I_NETSCAPE_RSA_2"},
{ERR_FUNC(ASN1_F_D2I_PRIVATEKEY), "d2i_PrivateKey"},
{ERR_FUNC(ASN1_F_D2I_PUBLICKEY), "d2i_PublicKey"},
{ERR_FUNC(ASN1_F_D2I_RSA_NET), "d2i_RSA_NET"},
{ERR_FUNC(ASN1_F_D2I_RSA_NET_2), "D2I_RSA_NET_2"},
{ERR_FUNC(ASN1_F_D2I_X509), "D2I_X509"},
{ERR_FUNC(ASN1_F_D2I_X509_CINF), "D2I_X509_CINF"},
{ERR_FUNC(ASN1_F_D2I_X509_PKEY), "d2i_X509_PKEY"},
{ERR_FUNC(ASN1_F_DO_BUF), "DO_BUF"},
{ERR_FUNC(ASN1_F_I2D_ASN1_BIO_STREAM), "i2d_ASN1_bio_stream"},
{ERR_FUNC(ASN1_F_I2D_ASN1_BOOLEAN), "i2d_ASN1_BOOLEAN"},
{ERR_FUNC(ASN1_F_I2D_ASN1_OBJECT), "i2d_ASN1_OBJECT"},
{ERR_FUNC(ASN1_F_I2D_ASN1_SET), "i2d_ASN1_SET"},
{ERR_FUNC(ASN1_F_I2D_ASN1_TIME), "I2D_ASN1_TIME"},
{ERR_FUNC(ASN1_F_I2D_DSA_PUBKEY), "i2d_DSA_PUBKEY"},
{ERR_FUNC(ASN1_F_I2D_EC_PUBKEY), "i2d_EC_PUBKEY"},
{ERR_FUNC(ASN1_F_I2D_PRIVATEKEY), "i2d_PrivateKey"},
{ERR_FUNC(ASN1_F_I2D_PUBLICKEY), "i2d_PublicKey"},
{ERR_FUNC(ASN1_F_I2D_RSA_NET), "i2d_RSA_NET"},
{ERR_FUNC(ASN1_F_I2D_RSA_PUBKEY), "i2d_RSA_PUBKEY"},
{ERR_FUNC(ASN1_F_LONG_C2I), "LONG_C2I"},
{ERR_FUNC(ASN1_F_OID_MODULE_INIT), "OID_MODULE_INIT"},
{ERR_FUNC(ASN1_F_PARSE_TAGGING), "PARSE_TAGGING"},
{ERR_FUNC(ASN1_F_PKCS5_PBE2_SET_IV), "PKCS5_pbe2_set_iv"},
{ERR_FUNC(ASN1_F_PKCS5_PBE_SET), "PKCS5_pbe_set"},
{ERR_FUNC(ASN1_F_PKCS5_PBE_SET0_ALGOR), "PKCS5_pbe_set0_algor"},
{ERR_FUNC(ASN1_F_PKCS5_PBKDF2_SET), "PKCS5_pbkdf2_set"},
{ERR_FUNC(ASN1_F_SMIME_READ_ASN1), "SMIME_read_ASN1"},
{ERR_FUNC(ASN1_F_SMIME_TEXT), "SMIME_text"},
{ERR_FUNC(ASN1_F_X509_CINF_NEW), "X509_CINF_NEW"},
{ERR_FUNC(ASN1_F_X509_CRL_ADD0_REVOKED), "X509_CRL_add0_revoked"},
{ERR_FUNC(ASN1_F_X509_INFO_NEW), "X509_INFO_new"},
{ERR_FUNC(ASN1_F_X509_NAME_ENCODE), "X509_NAME_ENCODE"},
{ERR_FUNC(ASN1_F_X509_NAME_EX_D2I), "X509_NAME_EX_D2I"},
{ERR_FUNC(ASN1_F_X509_NAME_EX_NEW), "X509_NAME_EX_NEW"},
{ERR_FUNC(ASN1_F_X509_NEW), "X509_NEW"},
{ERR_FUNC(ASN1_F_X509_PKEY_NEW), "X509_PKEY_new"},
{0, NULL}
};
static ERR_STRING_DATA ASN1_str_reasons[] = {
{ERR_REASON(ASN1_R_ADDING_OBJECT), "adding object"},
{ERR_REASON(ASN1_R_ASN1_PARSE_ERROR), "asn1 parse error"},
{ERR_REASON(ASN1_R_ASN1_SIG_PARSE_ERROR), "asn1 sig parse error"},
{ERR_REASON(ASN1_R_AUX_ERROR), "aux error"},
{ERR_REASON(ASN1_R_BAD_CLASS), "bad class"},
{ERR_REASON(ASN1_R_BAD_OBJECT_HEADER), "bad object header"},
{ERR_REASON(ASN1_R_BAD_PASSWORD_READ), "bad password read"},
{ERR_REASON(ASN1_R_BAD_TAG), "bad tag"},
{ERR_REASON(ASN1_R_BAD_TEMPLATE), "bad template"},
{ERR_REASON(ASN1_R_BMPSTRING_IS_WRONG_LENGTH),
"bmpstring is wrong length"},
{ERR_REASON(ASN1_R_BN_LIB), "bn lib"},
{ERR_REASON(ASN1_R_BOOLEAN_IS_WRONG_LENGTH), "boolean is wrong length"},
{ERR_REASON(ASN1_R_BUFFER_TOO_SMALL), "buffer too small"},
{ERR_REASON(ASN1_R_CIPHER_HAS_NO_OBJECT_IDENTIFIER),
"cipher has no object identifier"},
{ERR_REASON(ASN1_R_CONTEXT_NOT_INITIALISED), "context not initialised"},
{ERR_REASON(ASN1_R_DATA_IS_WRONG), "data is wrong"},
{ERR_REASON(ASN1_R_DECODE_ERROR), "decode error"},
{ERR_REASON(ASN1_R_DECODING_ERROR), "decoding error"},
{ERR_REASON(ASN1_R_DEPTH_EXCEEDED), "depth exceeded"},
{ERR_REASON(ASN1_R_DIGEST_AND_KEY_TYPE_NOT_SUPPORTED),
"digest and key type not supported"},
{ERR_REASON(ASN1_R_ENCODE_ERROR), "encode error"},
{ERR_REASON(ASN1_R_ERROR_GETTING_TIME), "error getting time"},
{ERR_REASON(ASN1_R_ERROR_LOADING_SECTION), "error loading section"},
{ERR_REASON(ASN1_R_ERROR_PARSING_SET_ELEMENT),
"error parsing set element"},
{ERR_REASON(ASN1_R_ERROR_SETTING_CIPHER_PARAMS),
"error setting cipher params"},
{ERR_REASON(ASN1_R_EXPECTING_AN_INTEGER), "expecting an integer"},
{ERR_REASON(ASN1_R_EXPECTING_AN_OBJECT), "expecting an object"},
{ERR_REASON(ASN1_R_EXPECTING_A_BOOLEAN), "expecting a boolean"},
{ERR_REASON(ASN1_R_EXPECTING_A_TIME), "expecting a time"},
{ERR_REASON(ASN1_R_EXPLICIT_LENGTH_MISMATCH), "explicit length mismatch"},
{ERR_REASON(ASN1_R_EXPLICIT_TAG_NOT_CONSTRUCTED),
"explicit tag not constructed"},
{ERR_REASON(ASN1_R_FIELD_MISSING), "field missing"},
{ERR_REASON(ASN1_R_FIRST_NUM_TOO_LARGE), "first num too large"},
{ERR_REASON(ASN1_R_HEADER_TOO_LONG), "header too long"},
{ERR_REASON(ASN1_R_ILLEGAL_BITSTRING_FORMAT), "illegal bitstring format"},
{ERR_REASON(ASN1_R_ILLEGAL_BOOLEAN), "illegal boolean"},
{ERR_REASON(ASN1_R_ILLEGAL_CHARACTERS), "illegal characters"},
{ERR_REASON(ASN1_R_ILLEGAL_FORMAT), "illegal format"},
{ERR_REASON(ASN1_R_ILLEGAL_HEX), "illegal hex"},
{ERR_REASON(ASN1_R_ILLEGAL_IMPLICIT_TAG), "illegal implicit tag"},
{ERR_REASON(ASN1_R_ILLEGAL_INTEGER), "illegal integer"},
{ERR_REASON(ASN1_R_ILLEGAL_NESTED_TAGGING), "illegal nested tagging"},
{ERR_REASON(ASN1_R_ILLEGAL_NULL), "illegal null"},
{ERR_REASON(ASN1_R_ILLEGAL_NULL_VALUE), "illegal null value"},
{ERR_REASON(ASN1_R_ILLEGAL_OBJECT), "illegal object"},
{ERR_REASON(ASN1_R_ILLEGAL_OPTIONAL_ANY), "illegal optional any"},
{ERR_REASON(ASN1_R_ILLEGAL_OPTIONS_ON_ITEM_TEMPLATE),
"illegal options on item template"},
{ERR_REASON(ASN1_R_ILLEGAL_TAGGED_ANY), "illegal tagged any"},
{ERR_REASON(ASN1_R_ILLEGAL_TIME_VALUE), "illegal time value"},
{ERR_REASON(ASN1_R_INTEGER_NOT_ASCII_FORMAT), "integer not ascii format"},
{ERR_REASON(ASN1_R_INTEGER_TOO_LARGE_FOR_LONG),
"integer too large for long"},
{ERR_REASON(ASN1_R_INVALID_BIT_STRING_BITS_LEFT),
"invalid bit string bits left"},
{ERR_REASON(ASN1_R_INVALID_BMPSTRING_LENGTH), "invalid bmpstring length"},
{ERR_REASON(ASN1_R_INVALID_DIGIT), "invalid digit"},
{ERR_REASON(ASN1_R_INVALID_MIME_TYPE), "invalid mime type"},
{ERR_REASON(ASN1_R_INVALID_MODIFIER), "invalid modifier"},
{ERR_REASON(ASN1_R_INVALID_NUMBER), "invalid number"},
{ERR_REASON(ASN1_R_INVALID_OBJECT_ENCODING), "invalid object encoding"},
{ERR_REASON(ASN1_R_INVALID_SEPARATOR), "invalid separator"},
{ERR_REASON(ASN1_R_INVALID_TIME_FORMAT), "invalid time format"},
{ERR_REASON(ASN1_R_INVALID_UNIVERSALSTRING_LENGTH),
"invalid universalstring length"},
{ERR_REASON(ASN1_R_INVALID_UTF8STRING), "invalid utf8string"},
{ERR_REASON(ASN1_R_IV_TOO_LARGE), "iv too large"},
{ERR_REASON(ASN1_R_LENGTH_ERROR), "length error"},
{ERR_REASON(ASN1_R_LIST_ERROR), "list error"},
{ERR_REASON(ASN1_R_MIME_NO_CONTENT_TYPE), "mime no content type"},
{ERR_REASON(ASN1_R_MIME_PARSE_ERROR), "mime parse error"},
{ERR_REASON(ASN1_R_MIME_SIG_PARSE_ERROR), "mime sig parse error"},
{ERR_REASON(ASN1_R_MISSING_EOC), "missing eoc"},
{ERR_REASON(ASN1_R_MISSING_SECOND_NUMBER), "missing second number"},
{ERR_REASON(ASN1_R_MISSING_VALUE), "missing value"},
{ERR_REASON(ASN1_R_MSTRING_NOT_UNIVERSAL), "mstring not universal"},
{ERR_REASON(ASN1_R_MSTRING_WRONG_TAG), "mstring wrong tag"},
{ERR_REASON(ASN1_R_NESTED_ASN1_STRING), "nested asn1 string"},
{ERR_REASON(ASN1_R_NESTED_TOO_DEEP), "nested too deep"},
{ERR_REASON(ASN1_R_NON_HEX_CHARACTERS), "non hex characters"},
{ERR_REASON(ASN1_R_NOT_ASCII_FORMAT), "not ascii format"},
{ERR_REASON(ASN1_R_NOT_ENOUGH_DATA), "not enough data"},
{ERR_REASON(ASN1_R_NO_CONTENT_TYPE), "no content type"},
{ERR_REASON(ASN1_R_NO_DEFAULT_DIGEST), "no default digest"},
{ERR_REASON(ASN1_R_NO_MATCHING_CHOICE_TYPE), "no matching choice type"},
{ERR_REASON(ASN1_R_NO_MULTIPART_BODY_FAILURE),
"no multipart body failure"},
{ERR_REASON(ASN1_R_NO_MULTIPART_BOUNDARY), "no multipart boundary"},
{ERR_REASON(ASN1_R_NO_SIG_CONTENT_TYPE), "no sig content type"},
{ERR_REASON(ASN1_R_NULL_IS_WRONG_LENGTH), "null is wrong length"},
{ERR_REASON(ASN1_R_OBJECT_NOT_ASCII_FORMAT), "object not ascii format"},
{ERR_REASON(ASN1_R_ODD_NUMBER_OF_CHARS), "odd number of chars"},
{ERR_REASON(ASN1_R_PRIVATE_KEY_HEADER_MISSING),
"private key header missing"},
{ERR_REASON(ASN1_R_SECOND_NUMBER_TOO_LARGE), "second number too large"},
{ERR_REASON(ASN1_R_SEQUENCE_LENGTH_MISMATCH), "sequence length mismatch"},
{ERR_REASON(ASN1_R_SEQUENCE_NOT_CONSTRUCTED), "sequence not constructed"},
{ERR_REASON(ASN1_R_SEQUENCE_OR_SET_NEEDS_CONFIG),
"sequence or set needs config"},
{ERR_REASON(ASN1_R_SHORT_LINE), "short line"},
{ERR_REASON(ASN1_R_SIG_INVALID_MIME_TYPE), "sig invalid mime type"},
{ERR_REASON(ASN1_R_STREAMING_NOT_SUPPORTED), "streaming not supported"},
{ERR_REASON(ASN1_R_STRING_TOO_LONG), "string too long"},
{ERR_REASON(ASN1_R_STRING_TOO_SHORT), "string too short"},
{ERR_REASON(ASN1_R_TAG_VALUE_TOO_HIGH), "tag value too high"},
{ERR_REASON(ASN1_R_THE_ASN1_OBJECT_IDENTIFIER_IS_NOT_KNOWN_FOR_THIS_MD),
"the asn1 object identifier is not known for this md"},
{ERR_REASON(ASN1_R_TIME_NOT_ASCII_FORMAT), "time not ascii format"},
{ERR_REASON(ASN1_R_TOO_LONG), "too long"},
{ERR_REASON(ASN1_R_TYPE_NOT_CONSTRUCTED), "type not constructed"},
{ERR_REASON(ASN1_R_TYPE_NOT_PRIMITIVE), "type not primitive"},
{ERR_REASON(ASN1_R_UNABLE_TO_DECODE_RSA_KEY), "unable to decode rsa key"},
{ERR_REASON(ASN1_R_UNABLE_TO_DECODE_RSA_PRIVATE_KEY),
"unable to decode rsa private key"},
{ERR_REASON(ASN1_R_UNEXPECTED_EOC), "unexpected eoc"},
{ERR_REASON(ASN1_R_UNIVERSALSTRING_IS_WRONG_LENGTH),
"universalstring is wrong length"},
{ERR_REASON(ASN1_R_UNKNOWN_FORMAT), "unknown format"},
{ERR_REASON(ASN1_R_UNKNOWN_MESSAGE_DIGEST_ALGORITHM),
"unknown message digest algorithm"},
{ERR_REASON(ASN1_R_UNKNOWN_OBJECT_TYPE), "unknown object type"},
{ERR_REASON(ASN1_R_UNKNOWN_PUBLIC_KEY_TYPE), "unknown public key type"},
{ERR_REASON(ASN1_R_UNKNOWN_SIGNATURE_ALGORITHM),
"unknown signature algorithm"},
{ERR_REASON(ASN1_R_UNKNOWN_TAG), "unknown tag"},
{ERR_REASON(ASN1_R_UNKOWN_FORMAT), "unknown format"},
{ERR_REASON(ASN1_R_UNSUPPORTED_ANY_DEFINED_BY_TYPE),
"unsupported any defined by type"},
{ERR_REASON(ASN1_R_UNSUPPORTED_CIPHER), "unsupported cipher"},
{ERR_REASON(ASN1_R_UNSUPPORTED_ENCRYPTION_ALGORITHM),
"unsupported encryption algorithm"},
{ERR_REASON(ASN1_R_UNSUPPORTED_PUBLIC_KEY_TYPE),
"unsupported public key type"},
{ERR_REASON(ASN1_R_UNSUPPORTED_TYPE), "unsupported type"},
{ERR_REASON(ASN1_R_WRONG_PUBLIC_KEY_TYPE), "wrong public key type"},
{ERR_REASON(ASN1_R_WRONG_TAG), "wrong tag"},
{ERR_REASON(ASN1_R_WRONG_TYPE), "wrong type"},
{0, NULL}
};
#endif
void ERR_load_ASN1_strings(void)
{
#ifndef OPENSSL_NO_ERR
if (ERR_func_error_string(ASN1_str_functs[0].error) == NULL) {
ERR_load_strings(0, ASN1_str_functs);
ERR_load_strings(0, ASN1_str_reasons);
}
#endif
}
@@ -0,0 +1,831 @@
/* asn1_gen.c */
/*
* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
* 2002.
*/
/* ====================================================================
* Copyright (c) 2002 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 "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(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(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(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(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;
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)
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:
if (orig_der)
OPENSSL_free(orig_der);
if (new_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))
arg->format = ASN1_GEN_FORMAT_ASCII;
else if (!strncmp(vstart, "UTF8", 4))
arg->format = ASN1_GEN_FORMAT_UTF8;
else if (!strncmp(vstart, "HEX", 3))
arg->format = ASN1_GEN_FORMAT_HEX;
else if (!strncmp(vstart, "BITLIST", 7))
arg->format = ASN1_GEN_FORMAT_BITLIST;
else {
ASN1err(ASN1_F_ASN1_CB, ASN1_R_UNKOWN_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;
break;
}
} 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()))
goto bad;
if (!(ret->value.asn1_string = ASN1_STRING_type_new(utype)))
goto bad;
ret->type = utype;
ret->value.asn1_string->data = der;
ret->value.asn1_string->length = derlen;
der = NULL;
bad:
if (der)
OPENSSL_free(der);
if (sk)
sk_ASN1_TYPE_pop_free(sk, ASN1_TYPE_free);
if (sect)
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 < sizeof(tnst) / sizeof(struct tag_name_st); i++, tntmp++) {
if ((len == tntmp->len) && !strncmp(tntmp->strnam, tagstr, len))
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())) {
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, (char *)str))) {
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))) {
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())) {
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())) {
ASN1err(ASN1_F_ASN1_STR2TYPE, ERR_R_MALLOC_FAILURE);
goto bad_form;
}
if (format == ASN1_GEN_FORMAT_HEX) {
if (!(rdata = string_to_hex((char *)str, &rdlen))) {
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;
break;
}
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;
}
@@ -0,0 +1,63 @@
/* asn1t.h */
/*
* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
* 2006.
*/
/* ====================================================================
* Copyright (c) 2006 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).
*
*/
/* Internal ASN1 template structures and functions: not for application use */
void asn1_item_combine_free(ASN1_VALUE **pval, const ASN1_ITEM *it,
int combine);
@@ -0,0 +1,483 @@
/* crypto/asn1/asn1_lib.c */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.]
*/
#include <stdio.h>
#include <limits.h>
#include "cryptlib.h"
#include <openssl/asn1.h>
#include <openssl/asn1_mac.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);
const char ASN1_version[] = "ASN.1" OPENSSL_VERSION_PTEXT;
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 0
fprintf(stderr, "p=%d + *plength=%ld > omax=%ld + *pp=%d (%d > %d)\n",
(int)p, *plength, omax, (int)*pp, (int)(p + *plength),
(int)(omax + *pp));
#endif
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);
}
static int asn1_get_length(const unsigned char **pp, int *inf, long *rl,
long max)
{
const unsigned char *p = *pp;
unsigned long ret = 0;
unsigned long i;
if (max-- < 1)
return 0;
if (*p == 0x80) {
*inf = 1;
ret = 0;
p++;
} else {
*inf = 0;
i = *p & 0x7f;
if (*(p++) & 0x80) {
if (i > sizeof(ret) || max < (long)i)
return 0;
while (i-- > 0) {
ret <<= 8L;
ret |= *(p++);
}
} else
ret = i;
}
if (ret > LONG_MAX)
return 0;
*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;
}
static int _asn1_Finish(ASN1_const_CTX *c)
{
if ((c->inf == (1 | V_ASN1_CONSTRUCTED)) && (!c->eos)) {
if (!ASN1_const_check_infinite_end(&c->p, c->slen)) {
c->error = ERR_R_MISSING_ASN1_EOS;
return (0);
}
}
if (((c->slen != 0) && !(c->inf & 1)) || ((c->slen < 0) && (c->inf & 1))) {
c->error = ERR_R_ASN1_LENGTH_MISMATCH;
return (0);
}
return (1);
}
int asn1_Finish(ASN1_CTX *c)
{
return _asn1_Finish((ASN1_const_CTX *)c);
}
int asn1_const_Finish(ASN1_const_CTX *c)
{
return _asn1_Finish(c);
}
int asn1_GetSequence(ASN1_const_CTX *c, long *length)
{
const unsigned char *q;
q = c->p;
c->inf = ASN1_get_object(&(c->p), &(c->slen), &(c->tag), &(c->xclass),
*length);
if (c->inf & 0x80) {
c->error = ERR_R_BAD_GET_ASN1_OBJECT_CALL;
return (0);
}
if (c->tag != V_ASN1_SEQUENCE) {
c->error = ERR_R_EXPECTING_AN_ASN1_SEQUENCE;
return (0);
}
(*length) -= (c->p - q);
if (c->max && (*length < 0)) {
c->error = ERR_R_ASN1_LENGTH_MISMATCH;
return (0);
}
if (c->inf == (1 | V_ASN1_CONSTRUCTED))
c->slen = *length;
c->eos = 0;
return (1);
}
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;
dst->flags = str->flags;
return 1;
}
ASN1_STRING *ASN1_STRING_dup(const ASN1_STRING *str)
{
ASN1_STRING *ret;
if (!str)
return NULL;
ret = ASN1_STRING_new();
if (!ret)
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;
if (c == NULL)
str->data = OPENSSL_malloc(len + 1);
else
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)
{
if (str->data)
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 = (ASN1_STRING *)OPENSSL_malloc(sizeof(ASN1_STRING));
if (ret == NULL) {
ASN1err(ASN1_F_ASN1_STRING_TYPE_NEW, ERR_R_MALLOC_FAILURE);
return (NULL);
}
ret->length = 0;
ret->type = type;
ret->data = NULL;
ret->flags = 0;
return (ret);
}
void ASN1_STRING_free(ASN1_STRING *a)
{
if (a == NULL)
return;
if (a->data && !(a->flags & ASN1_STRING_FLAG_NDEF))
OPENSSL_free(a->data);
OPENSSL_free(a);
}
void ASN1_STRING_clear_free(ASN1_STRING *a)
{
if (a && 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);
}
void asn1_add_error(const unsigned char *address, int offset)
{
char buf1[DECIMAL_SIZE(address) + 1], buf2[DECIMAL_SIZE(offset) + 1];
BIO_snprintf(buf1, sizeof(buf1), "%lu", (unsigned long)address);
BIO_snprintf(buf2, sizeof(buf2), "%d", offset);
ERR_add_error_data(4, "address=", buf1, " offset=", buf2);
}
int ASN1_STRING_length(const ASN1_STRING *x)
{
return M_ASN1_STRING_length(x);
}
void ASN1_STRING_length_set(ASN1_STRING *x, int len)
{
M_ASN1_STRING_length_set(x, len);
return;
}
int ASN1_STRING_type(ASN1_STRING *x)
{
return M_ASN1_STRING_type(x);
}
unsigned char *ASN1_STRING_data(ASN1_STRING *x)
{
return M_ASN1_STRING_data(x);
}
@@ -0,0 +1,136 @@
/* asn1t.h */
/*
* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
* 2006.
*/
/* ====================================================================
* Copyright (c) 2006 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).
*
*/
/* Internal ASN1 structures and functions: not for application use */
struct tm;
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 print context structure */
struct asn1_pctx_st {
unsigned long flags;
unsigned long nm_flags;
unsigned long cert_flags;
unsigned long oid_flags;
unsigned long str_flags;
} /* ASN1_PCTX */ ;
/* ASN1 public key method structure */
struct evp_pkey_asn1_method_st {
int pkey_id;
int pkey_base_id;
unsigned long pkey_flags;
char *pem_str;
char *info;
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 (*priv_decode) (EVP_PKEY *pk, 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);
int (*pkey_size) (const EVP_PKEY *pk);
int (*pkey_bits) (const EVP_PKEY *pk);
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);
int (*sig_print) (BIO *out,
const X509_ALGOR *sigalg, const ASN1_STRING *sig,
int indent, ASN1_PCTX *pctx);
void (*pkey_free) (EVP_PKEY *pkey);
int (*pkey_ctrl) (EVP_PKEY *pkey, int op, long arg1, void *arg2);
/* Legacy functions for old PEM */
int (*old_priv_decode) (EVP_PKEY *pkey,
const unsigned char **pder, int derlen);
int (*old_priv_encode) (const EVP_PKEY *pkey, unsigned char **pder);
/* Custom ASN1 signature verification */
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);
} /* EVP_PKEY_ASN1_METHOD */ ;
/*
* Method to handle CRL access. In general a CRL could be very large (several
* Mb) and can consume large amounts of resources if stored in memory by
* multiple processes. This method allows general CRL operations to be
* redirected to more efficient callbacks: for example a CRL entry database.
*/
#define X509_CRL_METHOD_DYNAMIC 1
struct x509_crl_method_st {
int flags;
int (*crl_init) (X509_CRL *crl);
int (*crl_free) (X509_CRL *crl);
int (*crl_lookup) (X509_CRL *crl, X509_REVOKED **ret,
ASN1_INTEGER *ser, X509_NAME *issuer);
int (*crl_verify) (X509_CRL *crl, EVP_PKEY *pk);
};
@@ -0,0 +1,424 @@
/* crypto/asn1/asn1_par.c */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.]
*/
#include <stdio.h>
#include "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;
#if 0
dump_indent = indent;
#else
dump_indent = 6; /* Because we know BIO_dump_indent() */
#endif
if (depth > ASN1_PARSE_MAXDEPTH) {
BIO_puts(bp, "BAD RECURSION DEPTH\n");
return 0;
}
p = *pp;
tot = p + length;
op = p - 1;
while ((p < tot) && (op < p)) {
op = p;
j = ASN1_get_object(&p, &len, &tag, &xclass, length);
#ifdef LINT
j = j;
#endif
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;
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)) {
sp = p;
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_write(bp, ":BAD OBJECT", 11) <= 0)
goto end;
}
} else if (tag == V_ASN1_BOOLEAN) {
int ii;
opp = op;
ii = d2i_ASN1_BOOLEAN(NULL, &opp, len + hl);
if (ii < 0) {
if (BIO_write(bp, "Bad boolean\n", 12) <= 0)
goto end;
}
BIO_printf(bp, ":%d", ii);
} 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;
}
}
if (os != NULL) {
M_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_write(bp, "BAD INTEGER", 11) <= 0)
goto end;
}
M_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_write(bp, "BAD ENUMERATED", 14) <= 0)
goto end;
}
M_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 (!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:
if (o != NULL)
ASN1_OBJECT_free(o);
if (os != NULL)
M_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];
}
@@ -0,0 +1,981 @@
/* asn_mime.c */
/*
* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
* project.
*/
/* ====================================================================
* Copyright (c) 1999-2023 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.
* ====================================================================
*
*/
#include <stdio.h>
#include <ctype.h>
#include "cryptlib.h"
#include <openssl/rand.h>
#include <openssl/x509.h>
#include <openssl/asn1.h>
#include <openssl/asn1t.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
*/
typedef struct {
char *param_name; /* Param name e.g. "micalg" */
char *param_value; /* Param value e.g. "sha1" */
} MIME_PARAM;
DECLARE_STACK_OF(MIME_PARAM)
IMPLEMENT_STACK_OF(MIME_PARAM)
typedef struct {
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 */
} MIME_HEADER;
DECLARE_STACK_OF(MIME_HEADER)
IMPLEMENT_STACK_OF(MIME_HEADER)
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(char *name, char *value);
static int mime_hdr_addparam(MIME_HEADER *mhdr, char *name, 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, char *bound, int blen);
static int multi_split(BIO *bio, char *bound, STACK_OF(BIO) **ret);
static int strip_eol(char *linebuf, int *plen);
static MIME_HEADER *mime_hdr_find(STACK_OF(MIME_HEADER) *hdrs, char *name);
static MIME_PARAM *mime_param_find(MIME_HEADER *hdr, 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) {
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()))) {
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 = 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;
break;
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 deteched 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))) {
ASN1err(ASN1_F_SMIME_READ_ASN1, ASN1_R_MIME_PARSE_ERROR);
return NULL;
}
if (!(hdr = mime_hdr_find(headers, "content-type")) || !hdr->value) {
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")) {
/* 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))) {
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")) || !hdr->value) {
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))) {
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))) {
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];
int ret;
/*
* 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)
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 {
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);
if (len)
BIO_write(out, linebuf, len);
if (eol)
BIO_write(out, "\r\n", 2);
}
}
ret = BIO_flush(out);
BIO_pop(out);
BIO_free(bf);
if (ret <= 0)
return 0;
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))) {
ASN1err(ASN1_F_SMIME_TEXT, ASN1_R_MIME_PARSE_ERROR);
return 0;
}
if (!(hdr = mime_hdr_find(headers, "content-type")) || !hdr->value) {
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, 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;
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) {
sk_BIO_push(parts, bpart);
return 1;
} else if (part) {
/* Strip CR+LF from linebuf */
next_eol = strip_eol(linebuf, &len);
if (first) {
first = 0;
if (bpart)
sk_BIO_push(parts, bpart);
bpart = BIO_new(BIO_s_mem());
if (bpart == NULL)
return 1;
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);
}
}
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;
STACK_OF(MIME_HEADER) *headers;
int len, state, save_state = 0;
headers = sk_MIME_HEADER_new(mime_hdr_cmp);
if (!headers)
return NULL;
while ((len = BIO_gets(bio, linebuf, MAX_SMLEN)) > 0) {
/* If whitespace at line start then continuation line */
if (mhdr && isspace((unsigned char)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;
mhdr = mime_hdr_new(ntmp, strip_ends(q));
sk_MIME_HEADER_push(headers, mhdr);
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) {
mhdr = mime_hdr_new(ntmp, strip_ends(q));
sk_MIME_HEADER_push(headers, mhdr);
} 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;
}
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 (!isspace((unsigned char)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 (isspace((unsigned char)c))
*p = 0;
else
return name;
}
return NULL;
}
static MIME_HEADER *mime_hdr_new(char *name, char *value)
{
MIME_HEADER *mhdr;
char *tmpname, *tmpval, *p;
int c;
if (name) {
if (!(tmpname = BUF_strdup(name)))
return NULL;
for (p = tmpname; *p; p++) {
c = (unsigned char)*p;
if (isupper(c)) {
c = tolower(c);
*p = c;
}
}
} else
tmpname = NULL;
if (value) {
if (!(tmpval = BUF_strdup(value)))
return NULL;
for (p = tmpval; *p; p++) {
c = (unsigned char)*p;
if (isupper(c)) {
c = tolower(c);
*p = c;
}
}
} else
tmpval = NULL;
mhdr = (MIME_HEADER *)OPENSSL_malloc(sizeof(MIME_HEADER));
if (!mhdr)
return NULL;
mhdr->name = tmpname;
mhdr->value = tmpval;
if (!(mhdr->params = sk_MIME_PARAM_new(mime_param_cmp)))
return NULL;
return mhdr;
}
static int mime_hdr_addparam(MIME_HEADER *mhdr, char *name, char *value)
{
char *tmpname, *tmpval, *p;
int c;
MIME_PARAM *mparam;
if (name) {
tmpname = BUF_strdup(name);
if (!tmpname)
return 0;
for (p = tmpname; *p; p++) {
c = (unsigned char)*p;
if (isupper(c)) {
c = tolower(c);
*p = c;
}
}
} else
tmpname = NULL;
if (value) {
tmpval = BUF_strdup(value);
if (!tmpval)
return 0;
} else
tmpval = NULL;
/* Parameter values are case sensitive so leave as is */
mparam = (MIME_PARAM *)OPENSSL_malloc(sizeof(MIME_PARAM));
if (!mparam)
return 0;
mparam->param_name = tmpname;
mparam->param_value = tmpval;
sk_MIME_PARAM_push(mhdr->params, mparam);
return 1;
}
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, char *name)
{
MIME_HEADER htmp;
int idx;
htmp.name = name;
idx = sk_MIME_HEADER_find(hdrs, &htmp);
if (idx < 0)
return NULL;
return sk_MIME_HEADER_value(hdrs, idx);
}
static MIME_PARAM *mime_param_find(MIME_HEADER *hdr, char *name)
{
MIME_PARAM param;
int idx;
param.param_name = name;
idx = sk_MIME_PARAM_find(hdr->params, &param);
if (idx < 0)
return NULL;
return sk_MIME_PARAM_value(hdr->params, idx);
}
static void mime_hdr_free(MIME_HEADER *hdr)
{
if (hdr->name)
OPENSSL_free(hdr->name);
if (hdr->value)
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)
{
if (param->param_name)
OPENSSL_free(param->param_name);
if (param->param_value)
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, 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) && !strncmp(line + 2, bound, blen)) {
if (!strncmp(line + blen + 2, "--", 2))
return 2;
else
return 1;
}
return 0;
}
static int strip_eol(char *linebuf, int *plen)
{
int len = *plen;
char *p, c;
int is_eol = 0;
p = linebuf + len - 1;
for (p = linebuf + len - 1; len > 0; len--, p--) {
c = *p;
if (c == '\n')
is_eol = 1;
else if (c != '\r')
break;
}
*plen = len;
return is_eol;
}
@@ -0,0 +1,153 @@
/* asn_moid.c */
/*
* Written by Stephen Henson (steve@openssl.org) for the OpenSSL project
* 2001.
*/
/* ====================================================================
* Copyright (c) 2001-2004 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 <ctype.h>
#include <openssl/crypto.h>
#include "cryptlib.h"
#include <openssl/conf.h>
#include <openssl/dso.h>
#include <openssl/x509.h>
/* Simple ASN1 OID module: add all objects in a given section */
static int do_create(char *value, 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))) {
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)
{
OBJ_cleanup();
}
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(char *value, char *name)
{
int nid;
ASN1_OBJECT *oid;
char *ln, *ostr, *p, *lntmp;
p = strrchr(value, ',');
if (!p) {
ln = name;
ostr = value;
} else {
ln = NULL;
ostr = p + 1;
if (!*ostr)
return 0;
while (isspace((unsigned char)*ostr))
ostr++;
}
nid = OBJ_create(ostr, name, ln);
if (nid == NID_undef)
return 0;
if (p) {
ln = value;
while (isspace((unsigned char)*ln))
ln++;
p--;
while (isspace((unsigned char)*p)) {
if (p == ln)
return 0;
p--;
}
p++;
lntmp = OPENSSL_malloc((p - ln) + 1);
if (lntmp == NULL)
return 0;
memcpy(lntmp, ln, p - ln);
lntmp[p - ln] = 0;
oid = OBJ_nid2obj(nid);
oid->ln = lntmp;
}
return 1;
}
@@ -0,0 +1,207 @@
/* asn_pack.c */
/*
* Written by Dr Stephen N Henson (steve@openssl.org) 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>
#ifndef NO_ASN1_OLD
/* ASN1 packing and unpacking functions */
/* Turn an ASN1 encoded SEQUENCE OF into a STACK of structures */
STACK_OF(OPENSSL_BLOCK) *ASN1_seq_unpack(const unsigned char *buf, int len,
d2i_of_void *d2i,
void (*free_func) (OPENSSL_BLOCK))
{
STACK_OF(OPENSSL_BLOCK) *sk;
const unsigned char *pbuf;
pbuf = buf;
if (!(sk = d2i_ASN1_SET(NULL, &pbuf, len, d2i, free_func,
V_ASN1_SEQUENCE, V_ASN1_UNIVERSAL)))
ASN1err(ASN1_F_ASN1_SEQ_UNPACK, ASN1_R_DECODE_ERROR);
return sk;
}
/*
* Turn a STACK structures into an ASN1 encoded SEQUENCE OF structure in a
* OPENSSL_malloc'ed buffer
*/
unsigned char *ASN1_seq_pack(STACK_OF(OPENSSL_BLOCK) *safes, i2d_of_void *i2d,
unsigned char **buf, int *len)
{
int safelen;
unsigned char *safe, *p;
if (!(safelen = i2d_ASN1_SET(safes, NULL, i2d, V_ASN1_SEQUENCE,
V_ASN1_UNIVERSAL, IS_SEQUENCE))) {
ASN1err(ASN1_F_ASN1_SEQ_PACK, ASN1_R_ENCODE_ERROR);
return NULL;
}
if (!(safe = OPENSSL_malloc(safelen))) {
ASN1err(ASN1_F_ASN1_SEQ_PACK, ERR_R_MALLOC_FAILURE);
return NULL;
}
p = safe;
i2d_ASN1_SET(safes, &p, i2d, V_ASN1_SEQUENCE, V_ASN1_UNIVERSAL,
IS_SEQUENCE);
if (len)
*len = safelen;
if (buf)
*buf = safe;
return safe;
}
/* Extract an ASN1 object from an ASN1_STRING */
void *ASN1_unpack_string(ASN1_STRING *oct, d2i_of_void *d2i)
{
const unsigned char *p;
char *ret;
p = oct->data;
if (!(ret = d2i(NULL, &p, oct->length)))
ASN1err(ASN1_F_ASN1_UNPACK_STRING, ASN1_R_DECODE_ERROR);
return ret;
}
/* Pack an ASN1 object into an ASN1_STRING */
ASN1_STRING *ASN1_pack_string(void *obj, i2d_of_void *i2d, ASN1_STRING **oct)
{
unsigned char *p;
ASN1_STRING *octmp;
if (!oct || !*oct) {
if (!(octmp = ASN1_STRING_new())) {
ASN1err(ASN1_F_ASN1_PACK_STRING, ERR_R_MALLOC_FAILURE);
return NULL;
}
if (oct)
*oct = octmp;
} else
octmp = *oct;
if (!(octmp->length = i2d(obj, NULL))) {
ASN1err(ASN1_F_ASN1_PACK_STRING, ASN1_R_ENCODE_ERROR);
goto err;
}
if (!(p = OPENSSL_malloc(octmp->length))) {
ASN1err(ASN1_F_ASN1_PACK_STRING, ERR_R_MALLOC_FAILURE);
goto err;
}
octmp->data = p;
i2d(obj, &p);
return octmp;
err:
if (!oct || !*oct) {
ASN1_STRING_free(octmp);
if (oct)
*oct = NULL;
}
return NULL;
}
#endif
/* ASN1_ITEM versions of the above */
ASN1_STRING *ASN1_item_pack(void *obj, const ASN1_ITEM *it, ASN1_STRING **oct)
{
ASN1_STRING *octmp;
if (!oct || !*oct) {
if (!(octmp = ASN1_STRING_new())) {
ASN1err(ASN1_F_ASN1_ITEM_PACK, ERR_R_MALLOC_FAILURE);
return NULL;
}
if (oct)
*oct = octmp;
} else
octmp = *oct;
if (octmp->data) {
OPENSSL_free(octmp->data);
octmp->data = NULL;
}
if (!(octmp->length = ASN1_item_i2d(obj, &octmp->data, it))) {
ASN1err(ASN1_F_ASN1_ITEM_PACK, ASN1_R_ENCODE_ERROR);
return NULL;
}
if (!octmp->data) {
ASN1err(ASN1_F_ASN1_ITEM_PACK, ERR_R_MALLOC_FAILURE);
return NULL;
}
return octmp;
}
/* Extract an ASN1 object from an ASN1_STRING */
void *ASN1_item_unpack(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)))
ASN1err(ASN1_F_ASN1_ITEM_UNPACK, ASN1_R_DECODE_ERROR);
return ret;
}
@@ -0,0 +1,489 @@
/* bio_asn1.c */
/*
* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
* project.
*/
/* ====================================================================
* Copyright (c) 2006-2023 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).
*
*/
/*
* 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 <openssl/bio.h>
#include <openssl/asn1.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 BIO_METHOD methods_asn1 = {
BIO_TYPE_ASN1,
"asn1",
asn1_bio_write,
asn1_bio_read,
asn1_bio_puts,
asn1_bio_gets,
asn1_bio_ctrl,
asn1_bio_new,
asn1_bio_free,
asn1_bio_callback_ctrl,
};
BIO_METHOD *BIO_f_asn1(void)
{
return (&methods_asn1);
}
static int asn1_bio_new(BIO *b)
{
BIO_ASN1_BUF_CTX *ctx;
ctx = OPENSSL_malloc(sizeof(BIO_ASN1_BUF_CTX));
if (!ctx)
return 0;
if (!asn1_bio_init(ctx, DEFAULT_ASN1_BUF_SIZE)) {
OPENSSL_free(ctx);
return 0;
}
b->init = 1;
b->ptr = (char *)ctx;
b->flags = 0;
return 1;
}
static int asn1_bio_init(BIO_ASN1_BUF_CTX *ctx, int size)
{
ctx->buf = OPENSSL_malloc(size);
if (!ctx->buf)
return 0;
ctx->bufsize = size;
ctx->bufpos = 0;
ctx->buflen = 0;
ctx->copylen = 0;
ctx->asn1_class = V_ASN1_UNIVERSAL;
ctx->asn1_tag = V_ASN1_OCTET_STRING;
ctx->ex_buf = NULL;
ctx->ex_len = 0;
ctx->ex_pos = 0;
ctx->state = ASN1_STATE_START;
ctx->prefix = ctx->prefix_free = ctx->suffix = ctx->suffix_free = NULL;
ctx->ex_arg = NULL;
return 1;
}
static int asn1_bio_free(BIO *b)
{
BIO_ASN1_BUF_CTX *ctx;
ctx = (BIO_ASN1_BUF_CTX *)b->ptr;
if (ctx == NULL)
return 0;
if (ctx->prefix_free != NULL)
ctx->prefix_free(b, &ctx->ex_buf, &ctx->ex_len, &ctx->ex_arg);
if (ctx->suffix_free != NULL)
ctx->suffix_free(b, &ctx->ex_buf, &ctx->ex_len, &ctx->ex_arg);
OPENSSL_free(ctx->buf);
OPENSSL_free(ctx);
b->init = 0;
b->ptr = NULL;
b->flags = 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;
if (!in || (inl < 0) || (b->next_bio == NULL))
return 0;
ctx = (BIO_ASN1_BUF_CTX *)b->ptr;
if (ctx == 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 -1;
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;
OPENSSL_assert(ctx->buflen <= ctx->bufsize);
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(b->next_bio, 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(b->next_bio, in, wrmax);
if (ret <= 0)
break;
wrlen += ret;
ctx->copylen -= ret;
in += ret;
inl -= ret;
if (ctx->copylen == 0)
ctx->state = ASN1_STATE_HEADER;
if (inl == 0)
goto done;
break;
default:
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(b->next_bio, 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)
{
if (!b->next_bio)
return 0;
return BIO_read(b->next_bio, 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)
{
if (!b->next_bio)
return 0;
return BIO_gets(b->next_bio, str, size);
}
static long asn1_bio_callback_ctrl(BIO *b, int cmd, bio_info_cb *fp)
{
if (b->next_bio == NULL)
return (0);
return BIO_callback_ctrl(b->next_bio, 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;
ctx = (BIO_ASN1_BUF_CTX *)b->ptr;
if (ctx == NULL)
return 0;
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 (!b->next_bio)
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(b->next_bio, cmd, arg1, arg2);
else {
BIO_clear_retry_flags(b);
return 0;
}
break;
default:
if (!b->next_bio)
return 0;
return BIO_ctrl(b->next_bio, 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);
}
@@ -0,0 +1,279 @@
/* bio_ndef.c */
/*
* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
* project.
*/
/* ====================================================================
* Copyright (c) 2008-2023 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.
* ====================================================================
*
*/
#include <sys/types.h>
#include <openssl/asn1.h>
#include <openssl/asn1t.h>
#include <openssl/bio.h>
#include <openssl/err.h>
#include <stdio.h>
#include <string.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
* approptiate 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);
/*
* On success, the returned BIO owns the input BIO as part of its BIO chain.
* On failure, NULL is returned and the input BIO is owned by the caller.
*
* Unfortunately cannot constify this due to CMS_stream() and PKCS7_stream()
*/
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;
BIO *pop_bio = NULL;
if (!aux || !aux->asn1_cb) {
ASN1err(ASN1_F_BIO_NEW_NDEF, ASN1_R_STREAMING_NOT_SUPPORTED);
return NULL;
}
ndef_aux = OPENSSL_malloc(sizeof(NDEF_SUPPORT));
memset(ndef_aux, 0, sizeof(NDEF_SUPPORT));
asn_bio = BIO_new(BIO_f_asn1());
/* ASN1 bio needs to be next to output BIO */
out = BIO_push(asn_bio, out);
if (!ndef_aux || !asn_bio || !out)
goto err;
pop_bio = asn_bio;
if (BIO_asn1_set_prefix(asn_bio, ndef_prefix, ndef_prefix_free) <= 0
|| BIO_asn1_set_suffix(asn_bio, ndef_suffix, ndef_suffix_free) <= 0
|| BIO_ctrl(asn_bio, BIO_C_SET_EX_ARG, 0, ndef_aux) <= 0)
goto err;
/*
* Now let the callback prepend any digest, cipher, etc., that the BIO's
* ASN1 structure needs.
*/
sarg.out = out;
sarg.ndef_bio = NULL;
sarg.boundary = NULL;
/*
* The asn1_cb(), must not have mutated asn_bio on error, leaving it in the
* middle of some partially built, but not returned BIO chain.
*/
if (aux->asn1_cb(ASN1_OP_STREAM_PRE, &val, it, &sarg) <= 0) {
/*
* ndef_aux is now owned by asn_bio so we must not free it in the err
* clean up block
*/
ndef_aux = NULL;
goto err;
}
/*
* We must not fail now because the callback has prepended additional
* BIOs to the chain
*/
ndef_aux->val = val;
ndef_aux->it = it;
ndef_aux->ndef_bio = sarg.ndef_bio;
ndef_aux->boundary = sarg.boundary;
ndef_aux->out = out;
ndef_aux->derbuf = NULL;
return sarg.ndef_bio;
err:
/* BIO_pop() is NULL safe */
(void)BIO_pop(pop_bio);
if (asn_bio)
BIO_free(asn_bio);
if (ndef_aux)
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);
p = OPENSSL_malloc(derlen);
if (!p)
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;
if (ndef_aux == NULL)
return 0;
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);
p = OPENSSL_malloc(derlen);
if (!p)
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;
}
@@ -0,0 +1,15 @@
/*
* Auto generated with chartype.pl script. Mask of various character
* properties
*/
static const unsigned char char_type[] = {
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, 2,
120, 0, 1, 40, 0, 0, 0, 16, 16, 16, 0, 25, 25, 16, 16, 16,
16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 9, 9, 16, 9, 16,
0, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 0, 1, 0, 0, 0,
0, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 0, 0, 0, 0, 2
};
@@ -0,0 +1,177 @@
/* crypto/asn1/d2i_pr.c */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.]
*/
#include <stdio.h>
#include "cryptlib.h"
#include <openssl/bn.h>
#include <openssl/evp.h>
#include <openssl/objects.h>
#ifndef OPENSSL_NO_ENGINE
# include <openssl/engine.h>
#endif
#include <openssl/x509.h>
#include <openssl/asn1.h>
#include "asn1_locl.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
if (ret->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 ((ret != NULL) && ((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);
}
@@ -0,0 +1,136 @@
/* crypto/asn1/d2i_pu.c */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.]
*/
#include <stdio.h>
#include "cryptlib.h"
#include <openssl/bn.h>
#include <openssl/evp.h>
#include <openssl/objects.h>
#include <openssl/asn1.h>
#ifndef OPENSSL_NO_RSA
# include <openssl/rsa.h>
#endif
#ifndef OPENSSL_NO_DSA
# include <openssl/dsa.h>
#endif
#ifndef OPENSSL_NO_EC
# include <openssl/ec.h>
#endif
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:
/* TMP UGLY CAST */
if ((ret->pkey.rsa = d2i_RSAPublicKey(NULL,
(const unsigned char **)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),
(const unsigned char **)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),
(const unsigned char **)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;
/* break; */
}
if (a != NULL)
(*a) = ret;
return (ret);
err:
if ((ret != NULL) && ((a == NULL) || (*a != ret)))
EVP_PKEY_free(ret);
return (NULL);
}
@@ -0,0 +1,195 @@
/* crypto/asn1/evp_asn1.c */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.]
*/
#include <stdio.h>
#include "cryptlib.h"
#include <openssl/asn1.h>
#include <openssl/asn1_mac.h>
int ASN1_TYPE_set_octetstring(ASN1_TYPE *a, unsigned char *data, int len)
{
ASN1_STRING *os;
if ((os = M_ASN1_OCTET_STRING_new()) == NULL)
return (0);
if (!M_ASN1_OCTET_STRING_set(os, data, len)) {
M_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(ASN1_TYPE *a, unsigned char *data, int max_len)
{
int ret, num;
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 = M_ASN1_STRING_data(a->value.octet_string);
ret = M_ASN1_STRING_length(a->value.octet_string);
if (ret < max_len)
num = ret;
else
num = max_len;
memcpy(data, p, num);
return (ret);
}
int ASN1_TYPE_set_int_octetstring(ASN1_TYPE *a, long num, unsigned char *data,
int len)
{
int n, size;
ASN1_OCTET_STRING os, *osp;
ASN1_INTEGER in;
unsigned char *p;
unsigned char buf[32]; /* when they have 256bit longs, I'll be in
* trouble */
in.data = buf;
in.length = 32;
os.data = data;
os.type = V_ASN1_OCTET_STRING;
os.length = len;
ASN1_INTEGER_set(&in, num);
n = i2d_ASN1_INTEGER(&in, NULL);
n += M_i2d_ASN1_OCTET_STRING(&os, NULL);
size = ASN1_object_size(1, n, V_ASN1_SEQUENCE);
if ((osp = ASN1_STRING_new()) == NULL)
return (0);
/* Grow the 'string' */
if (!ASN1_STRING_set(osp, NULL, size)) {
ASN1_STRING_free(osp);
return (0);
}
M_ASN1_STRING_length_set(osp, size);
p = M_ASN1_STRING_data(osp);
ASN1_put_object(&p, 1, n, V_ASN1_SEQUENCE, V_ASN1_UNIVERSAL);
i2d_ASN1_INTEGER(&in, &p);
M_i2d_ASN1_OCTET_STRING(&os, &p);
ASN1_TYPE_set(a, V_ASN1_SEQUENCE, osp);
return (1);
}
/*
* we return the actual length..., num may be missing, in which case, set it
* to zero
*/
/* int max_len: for returned value */
int ASN1_TYPE_get_int_octetstring(ASN1_TYPE *a, long *num,
unsigned char *data, int max_len)
{
int ret = -1, n;
ASN1_INTEGER *ai = NULL;
ASN1_OCTET_STRING *os = NULL;
const unsigned char *p;
long length;
ASN1_const_CTX c;
if ((a->type != V_ASN1_SEQUENCE) || (a->value.sequence == NULL)) {
goto err;
}
p = M_ASN1_STRING_data(a->value.sequence);
length = M_ASN1_STRING_length(a->value.sequence);
c.pp = &p;
c.p = p;
c.max = p + length;
c.error = ASN1_R_DATA_IS_WRONG;
M_ASN1_D2I_start_sequence();
c.q = c.p;
if ((ai = d2i_ASN1_INTEGER(NULL, &c.p, c.slen)) == NULL)
goto err;
c.slen -= (c.p - c.q);
c.q = c.p;
if ((os = d2i_ASN1_OCTET_STRING(NULL, &c.p, c.slen)) == NULL)
goto err;
c.slen -= (c.p - c.q);
if (!M_ASN1_D2I_end_sequence())
goto err;
if (num != NULL)
*num = ASN1_INTEGER_get(ai);
ret = M_ASN1_STRING_length(os);
if (max_len > ret)
n = ret;
else
n = max_len;
if (data != NULL)
memcpy(data, M_ASN1_STRING_data(os), n);
if (0) {
err:
ASN1err(ASN1_F_ASN1_TYPE_GET_INT_OCTETSTRING, ASN1_R_DATA_IS_WRONG);
}
if (os != NULL)
M_ASN1_OCTET_STRING_free(os);
if (ai != NULL)
M_ASN1_INTEGER_free(ai);
return (ret);
}
@@ -0,0 +1,203 @@
/* crypto/asn1/f_enum.c */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.]
*/
#include <stdio.h>
#include "cryptlib.h"
#include <openssl/buffer.h>
#include <openssl/asn1.h>
/* Based on a_int.c: equivalent ENUMERATED functions */
int i2a_ASN1_ENUMERATED(BIO *bp, ASN1_ENUMERATED *a)
{
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, "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_ENUMERATED(BIO *bp, ASN1_ENUMERATED *bs, char *buf, int size)
{
int ret = 0;
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_ENUMERATED;
bufsize = BIO_gets(bp, buf, size);
for (;;) {
if (bufsize < 1)
goto err_sl;
i = bufsize;
if (buf[i - 1] == '\n')
buf[--i] = '\0';
if (i == 0)
goto err_sl;
if (buf[i - 1] == '\r')
buf[--i] = '\0';
if (i == 0)
goto err_sl;
again = (buf[i - 1] == '\\');
for (j = 0; j < i; j++) {
if (!(((buf[j] >= '0') && (buf[j] <= '9')) ||
((buf[j] >= 'a') && (buf[j] <= 'f')) ||
((buf[j] >= 'A') && (buf[j] <= 'F')))) {
i = j;
break;
}
}
buf[i] = '\0';
/*
* We have now cleared all the crap off the end of the line
*/
if (i < 2)
goto err_sl;
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_ENUMERATED, ASN1_R_ODD_NUMBER_OF_CHARS);
goto err;
}
i /= 2;
if (num + i > slen) {
if (s == NULL)
sp = (unsigned char *)OPENSSL_malloc((unsigned int)num +
i * 2);
else
sp = (unsigned char *)OPENSSL_realloc(s,
(unsigned int)num +
i * 2);
if (sp == NULL) {
ASN1err(ASN1_F_A2I_ASN1_ENUMERATED, ERR_R_MALLOC_FAILURE);
goto err;
}
s = sp;
slen = num + i * 2;
}
for (j = 0; j < i; j++, k += 2) {
for (n = 0; n < 2; n++) {
m = bufp[k + n];
if ((m >= '0') && (m <= '9'))
m -= '0';
else if ((m >= 'a') && (m <= 'f'))
m = m - 'a' + 10;
else if ((m >= 'A') && (m <= 'F'))
m = m - 'A' + 10;
else {
ASN1err(ASN1_F_A2I_ASN1_ENUMERATED,
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;
ret = 1;
err:
if (0) {
err_sl:
ASN1err(ASN1_F_A2I_ASN1_ENUMERATED, ASN1_R_SHORT_LINE);
}
if (ret != 1)
OPENSSL_free(s);
return (ret);
}
@@ -0,0 +1,215 @@
/* crypto/asn1/f_int.c */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.]
*/
#include <stdio.h>
#include "cryptlib.h"
#include <openssl/buffer.h>
#include <openssl/asn1.h>
int i2a_ASN1_INTEGER(BIO *bp, 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 ret = 0;
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_sl;
i = bufsize;
if (buf[i - 1] == '\n')
buf[--i] = '\0';
if (i == 0)
goto err_sl;
if (buf[i - 1] == '\r')
buf[--i] = '\0';
if (i == 0)
goto err_sl;
again = (buf[i - 1] == '\\');
for (j = 0; j < i; j++) {
#ifndef CHARSET_EBCDIC
if (!(((buf[j] >= '0') && (buf[j] <= '9')) ||
((buf[j] >= 'a') && (buf[j] <= 'f')) ||
((buf[j] >= 'A') && (buf[j] <= 'F'))))
#else
/*
* This #ifdef is not strictly necessary, since the characters
* A...F a...f 0...9 are contiguous (yes, even in EBCDIC - but
* not the whole alphabet). Nevertheless, isxdigit() is faster.
*/
if (!isxdigit(buf[j]))
#endif
{
i = j;
break;
}
}
buf[i] = '\0';
/*
* We have now cleared all the crap off the end of the line
*/
if (i < 2)
goto err_sl;
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);
goto err;
}
i /= 2;
if (num + i > slen) {
if (s == NULL)
sp = (unsigned char *)OPENSSL_malloc((unsigned int)num +
i * 2);
else
sp = OPENSSL_realloc_clean(s, slen, num + i * 2);
if (sp == NULL) {
ASN1err(ASN1_F_A2I_ASN1_INTEGER, ERR_R_MALLOC_FAILURE);
goto err;
}
s = sp;
slen = num + i * 2;
}
for (j = 0; j < i; j++, k += 2) {
for (n = 0; n < 2; n++) {
m = bufp[k + n];
if ((m >= '0') && (m <= '9'))
m -= '0';
else if ((m >= 'a') && (m <= 'f'))
m = m - 'a' + 10;
else if ((m >= 'A') && (m <= 'F'))
m = m - 'A' + 10;
else {
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;
ret = 1;
err:
if (0) {
err_sl:
ASN1err(ASN1_F_A2I_ASN1_INTEGER, ASN1_R_SHORT_LINE);
}
if (ret != 1)
OPENSSL_free(s);
return (ret);
}
@@ -0,0 +1,209 @@
/* crypto/asn1/f_string.c */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.]
*/
#include <stdio.h>
#include "cryptlib.h"
#include <openssl/buffer.h>
#include <openssl/asn1.h>
int i2a_ASN1_STRING(BIO *bp, 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 ret = 0;
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_sl;
}
first = 0;
i = bufsize;
if (buf[i - 1] == '\n')
buf[--i] = '\0';
if (i == 0)
goto err_sl;
if (buf[i - 1] == '\r')
buf[--i] = '\0';
if (i == 0)
goto err_sl;
again = (buf[i - 1] == '\\');
for (j = i - 1; j > 0; j--) {
#ifndef CHARSET_EBCDIC
if (!(((buf[j] >= '0') && (buf[j] <= '9')) ||
((buf[j] >= 'a') && (buf[j] <= 'f')) ||
((buf[j] >= 'A') && (buf[j] <= 'F'))))
#else
/*
* This #ifdef is not strictly necessary, since the characters
* A...F a...f 0...9 are contiguous (yes, even in EBCDIC - but
* not the whole alphabet). Nevertheless, isxdigit() is faster.
*/
if (!isxdigit(buf[j]))
#endif
{
i = j;
break;
}
}
buf[i] = '\0';
/*
* We have now cleared all the crap off the end of the line
*/
if (i < 2)
goto err_sl;
bufp = (unsigned char *)buf;
k = 0;
i -= again;
if (i % 2 != 0) {
ASN1err(ASN1_F_A2I_ASN1_STRING, ASN1_R_ODD_NUMBER_OF_CHARS);
goto err;
}
i /= 2;
if (num + i > slen) {
if (s == NULL)
sp = (unsigned char *)OPENSSL_malloc((unsigned int)num +
i * 2);
else
sp = (unsigned char *)OPENSSL_realloc(s,
(unsigned int)num +
i * 2);
if (sp == NULL) {
ASN1err(ASN1_F_A2I_ASN1_STRING, ERR_R_MALLOC_FAILURE);
goto err;
}
s = sp;
slen = num + i * 2;
}
for (j = 0; j < i; j++, k += 2) {
for (n = 0; n < 2; n++) {
m = bufp[k + n];
if ((m >= '0') && (m <= '9'))
m -= '0';
else if ((m >= 'a') && (m <= 'f'))
m = m - 'a' + 10;
else if ((m >= 'A') && (m <= 'F'))
m = m - 'A' + 10;
else {
ASN1err(ASN1_F_A2I_ASN1_STRING,
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;
ret = 1;
err:
if (0) {
err_sl:
ASN1err(ASN1_F_A2I_ASN1_STRING, ASN1_R_SHORT_LINE);
}
if (ret != 1)
OPENSSL_free(s);
return (ret);
}
@@ -0,0 +1,81 @@
/* crypto/asn1/i2d_pr.c */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.]
*/
#include <stdio.h>
#include "cryptlib.h"
#include <openssl/evp.h>
#include <openssl/x509.h>
#include "asn1_locl.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;
}
@@ -0,0 +1,93 @@
/* crypto/asn1/i2d_pu.c */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.]
*/
#include <stdio.h>
#include "cryptlib.h"
#include <openssl/bn.h>
#include <openssl/evp.h>
#include <openssl/objects.h>
#ifndef OPENSSL_NO_RSA
# include <openssl/rsa.h>
#endif
#ifndef OPENSSL_NO_DSA
# include <openssl/dsa.h>
#endif
#ifndef OPENSSL_NO_EC
# include <openssl/ec.h>
#endif
int i2d_PublicKey(EVP_PKEY *a, unsigned char **pp)
{
switch (a->type) {
#ifndef OPENSSL_NO_RSA
case EVP_PKEY_RSA:
return (i2d_RSAPublicKey(a->pkey.rsa, pp));
#endif
#ifndef OPENSSL_NO_DSA
case EVP_PKEY_DSA:
return (i2d_DSAPublicKey(a->pkey.dsa, pp));
#endif
#ifndef OPENSSL_NO_EC
case EVP_PKEY_EC:
return (i2o_ECPublicKey(a->pkey.ec, pp));
#endif
default:
ASN1err(ASN1_F_I2D_PUBLICKEY, ASN1_R_UNSUPPORTED_PUBLIC_KEY_TYPE);
return (-1);
}
}
@@ -0,0 +1,346 @@
/* crypto/asn1/n_pkey.c */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.]
*/
#include <stdio.h>
#include <stddef.h>
#include "cryptlib.h"
#ifndef OPENSSL_NO_RSA
# include <openssl/rsa.h>
# include <openssl/objects.h>
# include <openssl/asn1t.h>
# include <openssl/asn1_mac.h>
# include <openssl/evp.h>
# include <openssl/x509.h>
# ifndef OPENSSL_NO_RC4
typedef struct netscape_pkey_st {
long 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)
} 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_SIMPLE(NETSCAPE_PKEY, version, LONG),
ASN1_SIMPLE(NETSCAPE_PKEY, algor, X509_ALGOR),
ASN1_SIMPLE(NETSCAPE_PKEY, private_key, ASN1_OCTET_STRING)
} 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)
static RSA *d2i_RSA_NET_2(RSA **a, ASN1_OCTET_STRING *os,
int (*cb) (char *buf, int len, const char *prompt,
int verify), int sgckey);
int i2d_Netscape_RSA(const RSA *a, unsigned char **pp,
int (*cb) (char *buf, int len, const char *prompt,
int verify))
{
return i2d_RSA_NET(a, pp, cb, 0);
}
int i2d_RSA_NET(const RSA *a, unsigned char **pp,
int (*cb) (char *buf, int len, const char *prompt,
int verify), int sgckey)
{
int i, j, ret = 0;
int rsalen, pkeylen, olen;
NETSCAPE_PKEY *pkey = NULL;
NETSCAPE_ENCRYPTED_PKEY *enckey = NULL;
unsigned char buf[256], *zz;
unsigned char key[EVP_MAX_KEY_LENGTH];
EVP_CIPHER_CTX ctx;
EVP_CIPHER_CTX_init(&ctx);
if (a == NULL)
return (0);
if ((pkey = NETSCAPE_PKEY_new()) == NULL)
goto err;
if ((enckey = NETSCAPE_ENCRYPTED_PKEY_new()) == NULL)
goto err;
pkey->version = 0;
pkey->algor->algorithm = OBJ_nid2obj(NID_rsaEncryption);
if ((pkey->algor->parameter = ASN1_TYPE_new()) == NULL)
goto err;
pkey->algor->parameter->type = V_ASN1_NULL;
rsalen = i2d_RSAPrivateKey(a, NULL);
/*
* Fake some octet strings just for the initial length calculation.
*/
pkey->private_key->length = rsalen;
pkeylen = i2d_NETSCAPE_PKEY(pkey, NULL);
enckey->enckey->digest->length = pkeylen;
enckey->os->length = 11; /* "private-key" */
enckey->enckey->algor->algorithm = OBJ_nid2obj(NID_rc4);
if ((enckey->enckey->algor->parameter = ASN1_TYPE_new()) == NULL)
goto err;
enckey->enckey->algor->parameter->type = V_ASN1_NULL;
if (pp == NULL) {
olen = i2d_NETSCAPE_ENCRYPTED_PKEY(enckey, NULL);
NETSCAPE_PKEY_free(pkey);
NETSCAPE_ENCRYPTED_PKEY_free(enckey);
return olen;
}
/* Since its RC4 encrypted length is actual length */
if ((zz = (unsigned char *)OPENSSL_malloc(rsalen)) == NULL) {
ASN1err(ASN1_F_I2D_RSA_NET, ERR_R_MALLOC_FAILURE);
goto err;
}
pkey->private_key->data = zz;
/* Write out private key encoding */
i2d_RSAPrivateKey(a, &zz);
if ((zz = OPENSSL_malloc(pkeylen)) == NULL) {
ASN1err(ASN1_F_I2D_RSA_NET, ERR_R_MALLOC_FAILURE);
goto err;
}
if (!ASN1_STRING_set(enckey->os, "private-key", -1)) {
ASN1err(ASN1_F_I2D_RSA_NET, ERR_R_MALLOC_FAILURE);
goto err;
}
enckey->enckey->digest->data = zz;
i2d_NETSCAPE_PKEY(pkey, &zz);
/* Wipe the private key encoding */
OPENSSL_cleanse(pkey->private_key->data, rsalen);
if (cb == NULL)
cb = EVP_read_pw_string;
i = cb((char *)buf, 256, "Enter Private Key password:", 1);
if (i != 0) {
ASN1err(ASN1_F_I2D_RSA_NET, ASN1_R_BAD_PASSWORD_READ);
goto err;
}
i = strlen((char *)buf);
/* If the key is used for SGC the algorithm is modified a little. */
if (sgckey) {
if (!EVP_Digest(buf, i, buf, NULL, EVP_md5(), NULL))
goto err;
memcpy(buf + 16, "SGCKEYSALT", 10);
i = 26;
}
if (!EVP_BytesToKey(EVP_rc4(), EVP_md5(), NULL, buf, i, 1, key, NULL))
goto err;
OPENSSL_cleanse(buf, 256);
/* Encrypt private key in place */
zz = enckey->enckey->digest->data;
if (!EVP_EncryptInit_ex(&ctx, EVP_rc4(), NULL, key, NULL))
goto err;
if (!EVP_EncryptUpdate(&ctx, zz, &i, zz, pkeylen))
goto err;
if (!EVP_EncryptFinal_ex(&ctx, zz + i, &j))
goto err;
ret = i2d_NETSCAPE_ENCRYPTED_PKEY(enckey, pp);
err:
EVP_CIPHER_CTX_cleanup(&ctx);
NETSCAPE_ENCRYPTED_PKEY_free(enckey);
NETSCAPE_PKEY_free(pkey);
return (ret);
}
RSA *d2i_Netscape_RSA(RSA **a, const unsigned char **pp, long length,
int (*cb) (char *buf, int len, const char *prompt,
int verify))
{
return d2i_RSA_NET(a, pp, length, cb, 0);
}
RSA *d2i_RSA_NET(RSA **a, const unsigned char **pp, long length,
int (*cb) (char *buf, int len, const char *prompt,
int verify), int sgckey)
{
RSA *ret = NULL;
const unsigned char *p;
NETSCAPE_ENCRYPTED_PKEY *enckey = NULL;
p = *pp;
enckey = d2i_NETSCAPE_ENCRYPTED_PKEY(NULL, &p, length);
if (!enckey) {
ASN1err(ASN1_F_D2I_RSA_NET, ASN1_R_DECODING_ERROR);
return NULL;
}
if ((enckey->os->length != 11) || (strncmp("private-key",
(char *)enckey->os->data,
11) != 0)) {
ASN1err(ASN1_F_D2I_RSA_NET, ASN1_R_PRIVATE_KEY_HEADER_MISSING);
NETSCAPE_ENCRYPTED_PKEY_free(enckey);
return NULL;
}
if (OBJ_obj2nid(enckey->enckey->algor->algorithm) != NID_rc4) {
ASN1err(ASN1_F_D2I_RSA_NET, ASN1_R_UNSUPPORTED_ENCRYPTION_ALGORITHM);
goto err;
}
if (cb == NULL)
cb = EVP_read_pw_string;
if ((ret = d2i_RSA_NET_2(a, enckey->enckey->digest, cb, sgckey)) == NULL)
goto err;
*pp = p;
err:
NETSCAPE_ENCRYPTED_PKEY_free(enckey);
return ret;
}
static RSA *d2i_RSA_NET_2(RSA **a, ASN1_OCTET_STRING *os,
int (*cb) (char *buf, int len, const char *prompt,
int verify), int sgckey)
{
NETSCAPE_PKEY *pkey = NULL;
RSA *ret = NULL;
int i, j;
unsigned char buf[256];
const unsigned char *zz;
unsigned char key[EVP_MAX_KEY_LENGTH];
EVP_CIPHER_CTX ctx;
EVP_CIPHER_CTX_init(&ctx);
i = cb((char *)buf, 256, "Enter Private Key password:", 0);
if (i != 0) {
ASN1err(ASN1_F_D2I_RSA_NET_2, ASN1_R_BAD_PASSWORD_READ);
goto err;
}
i = strlen((char *)buf);
if (sgckey) {
if (!EVP_Digest(buf, i, buf, NULL, EVP_md5(), NULL))
goto err;
memcpy(buf + 16, "SGCKEYSALT", 10);
i = 26;
}
if (!EVP_BytesToKey(EVP_rc4(), EVP_md5(), NULL, buf, i, 1, key, NULL))
goto err;
OPENSSL_cleanse(buf, 256);
if (!EVP_DecryptInit_ex(&ctx, EVP_rc4(), NULL, key, NULL))
goto err;
if (!EVP_DecryptUpdate(&ctx, os->data, &i, os->data, os->length))
goto err;
if (!EVP_DecryptFinal_ex(&ctx, &(os->data[i]), &j))
goto err;
os->length = i + j;
zz = os->data;
if ((pkey = d2i_NETSCAPE_PKEY(NULL, &zz, os->length)) == NULL) {
ASN1err(ASN1_F_D2I_RSA_NET_2,
ASN1_R_UNABLE_TO_DECODE_RSA_PRIVATE_KEY);
goto err;
}
zz = pkey->private_key->data;
if ((ret = d2i_RSAPrivateKey(a, &zz, pkey->private_key->length)) == NULL) {
ASN1err(ASN1_F_D2I_RSA_NET_2, ASN1_R_UNABLE_TO_DECODE_RSA_KEY);
goto err;
}
err:
EVP_CIPHER_CTX_cleanup(&ctx);
NETSCAPE_PKEY_free(pkey);
return (ret);
}
# endif /* OPENSSL_NO_RC4 */
#else /* !OPENSSL_NO_RSA */
# if PEDANTIC
static void *dummy = &dummy;
# endif
#endif
@@ -0,0 +1,85 @@
/* nsseq.c */
/*
* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
* 1999.
*/
/* ====================================================================
* Copyright (c) 1999-2005 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 <stddef.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)
@@ -0,0 +1,144 @@
/* p5_pbe.c */
/*
* Written by Dr Stephen N Henson (steve@openssl.org) 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 <stddef.h>
#include "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;
pbe = PBEPARAM_new();
if (!pbe) {
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;
if (!ASN1_STRING_set(pbe->salt, NULL, saltlen)) {
ASN1err(ASN1_F_PKCS5_PBE_SET0_ALGOR, ERR_R_MALLOC_FAILURE);
goto err;
}
sstr = ASN1_STRING_data(pbe->salt);
if (salt)
memcpy(sstr, salt, saltlen);
else if (RAND_bytes(sstr, saltlen) <= 0)
goto err;
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:
if (pbe != NULL)
PBEPARAM_free(pbe);
if (pbe_str != NULL)
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) {
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;
}
@@ -0,0 +1,278 @@
/* p5_pbev2.c */
/*
* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
* 1999-2004.
*/
/* ====================================================================
* 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 <stddef.h>
#include <sys/types.h>
#include "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;
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()))
goto merr;
/* Setup the AlgorithmIdentifier for the encryption scheme */
scheme = pbe2->encryption;
scheme->algorithm = OBJ_nid2obj(alg_nid);
if (!(scheme->parameter = ASN1_TYPE_new()))
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;
}
EVP_CIPHER_CTX_init(&ctx);
/* 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);
EVP_CIPHER_CTX_cleanup(&ctx);
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_hmacWithSHA1;
}
EVP_CIPHER_CTX_cleanup(&ctx);
/* 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()))
goto merr;
if (!(ret->parameter = ASN1_TYPE_new()))
goto merr;
ret->algorithm = OBJ_nid2obj(NID_pbes2);
/* Encode PBE2PARAM into parameter */
if (!ASN1_item_pack(pbe2, ASN1_ITEM_rptr(PBE2PARAM),
&ret->parameter->value.sequence))
goto merr;
ret->parameter->type = V_ASN1_SEQUENCE;
PBE2PARAM_free(pbe2);
pbe2 = NULL;
return ret;
merr:
ASN1err(ASN1_F_PKCS5_PBE2_SET_IV, ERR_R_MALLOC_FAILURE);
err:
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()))
goto merr;
if (!(osalt = M_ASN1_OCTET_STRING_new()))
goto merr;
kdf->salt->value.octet_string = osalt;
kdf->salt->type = V_ASN1_OCTET_STRING;
if (!saltlen)
saltlen = PKCS5_SALT_LEN;
if (!(osalt->data = OPENSSL_malloc(saltlen)))
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 = M_ASN1_INTEGER_new()))
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)
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)
goto merr;
keyfunc->algorithm = OBJ_nid2obj(NID_id_pbkdf2);
/* Encode PBKDF2PARAM into parameter of pbe2 */
if (!(keyfunc->parameter = ASN1_TYPE_new()))
goto merr;
if (!ASN1_item_pack(kdf, ASN1_ITEM_rptr(PBKDF2PARAM),
&keyfunc->parameter->value.sequence))
goto merr;
keyfunc->parameter->type = V_ASN1_SEQUENCE;
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;
}
@@ -0,0 +1,146 @@
/* p8_pkey.c */
/*
* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
* 1999.
*/
/* ====================================================================
* Copyright (c) 1999-2005 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 <stddef.h>
#include "cryptlib.h"
#include <openssl/asn1t.h>
#include <openssl/x509.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 && key->pkey->type == V_ASN1_OCTET_STRING
&& key->pkey->value.octet_string != NULL)
OPENSSL_cleanse(key->pkey->value.octet_string->data,
key->pkey->value.octet_string->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_ANY),
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)
{
unsigned char **ppenc = NULL;
if (version >= 0) {
if (!ASN1_INTEGER_set(priv->version, version))
return 0;
}
if (penc) {
int pmtype;
ASN1_OCTET_STRING *oct;
oct = ASN1_OCTET_STRING_new();
if (!oct)
return 0;
oct->data = penc;
ppenc = &oct->data;
oct->length = penclen;
if (priv->broken == PKCS8_NO_OCTET)
pmtype = V_ASN1_SEQUENCE;
else
pmtype = V_ASN1_OCTET_STRING;
ASN1_TYPE_set(priv->pkey, pmtype, oct);
}
if (!X509_ALGOR_set0(priv->pkeyalg, aobj, ptype, pval)) {
/* If call fails do not swallow 'enc' */
if (ppenc)
*ppenc = NULL;
return 0;
}
return 1;
}
int PKCS8_pkey_get0(ASN1_OBJECT **ppkalg,
const unsigned char **pk, int *ppklen,
X509_ALGOR **pa, PKCS8_PRIV_KEY_INFO *p8)
{
if (ppkalg)
*ppkalg = p8->pkeyalg->algorithm;
if (p8->pkey->type == V_ASN1_OCTET_STRING) {
p8->broken = PKCS8_OK;
if (pk) {
*pk = p8->pkey->value.octet_string->data;
*ppklen = p8->pkey->value.octet_string->length;
}
} else if (p8->pkey->type == V_ASN1_SEQUENCE) {
p8->broken = PKCS8_NO_OCTET;
if (pk) {
*pk = p8->pkey->value.sequence->data;
*ppklen = p8->pkey->value.sequence->length;
}
} else
return 0;
if (pa)
*pa = p8->pkeyalg;
return 1;
}
@@ -0,0 +1,105 @@
/* t_bitst.c */
/*
* Written by Dr Stephen N Henson (steve@openssl.org) 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/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, 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(char *name, BIT_STRING_BITNAME *tbl)
{
BIT_STRING_BITNAME *bnam;
for (bnam = tbl; bnam->lname; bnam++) {
if (!strcmp(bnam->sname, name) || !strcmp(bnam->lname, name))
return bnam->bitnum;
}
return -1;
}
@@ -0,0 +1,133 @@
/* t_crl.c */
/*
* Written by Dr Stephen N Henson (steve@openssl.org) 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/buffer.h>
#include <openssl/bn.h>
#include <openssl/objects.h>
#include <openssl/x509.h>
#include <openssl/x509v3.h>
#ifndef OPENSSL_NO_FP_API
int X509_CRL_print_fp(FILE *fp, X509_CRL *x)
{
BIO *b;
int ret;
if ((b = BIO_new(BIO_s_file())) == NULL) {
X509err(X509_F_X509_CRL_PRINT_FP, ERR_R_BUF_LIB);
return (0);
}
BIO_set_fp(b, fp, BIO_NOCLOSE);
ret = X509_CRL_print(b, x);
BIO_free(b);
return (ret);
}
#endif
int X509_CRL_print(BIO *out, X509_CRL *x)
{
STACK_OF(X509_REVOKED) *rev;
X509_REVOKED *r;
long l;
int i;
char *p;
BIO_printf(out, "Certificate Revocation List (CRL):\n");
l = X509_CRL_get_version(x);
BIO_printf(out, "%8sVersion %lu (0x%lx)\n", "", l + 1, l);
i = OBJ_obj2nid(x->sig_alg->algorithm);
X509_signature_print(out, x->sig_alg, NULL);
p = X509_NAME_oneline(X509_CRL_get_issuer(x), NULL, 0);
BIO_printf(out, "%8sIssuer: %s\n", "", p);
OPENSSL_free(p);
BIO_printf(out, "%8sLast Update: ", "");
ASN1_TIME_print(out, X509_CRL_get_lastUpdate(x));
BIO_printf(out, "\n%8sNext Update: ", "");
if (X509_CRL_get_nextUpdate(x))
ASN1_TIME_print(out, X509_CRL_get_nextUpdate(x));
else
BIO_printf(out, "NONE");
BIO_printf(out, "\n");
X509V3_extensions_print(out, "CRL extensions", x->crl->extensions, 0, 8);
rev = X509_CRL_get_REVOKED(x);
if (sk_X509_REVOKED_num(rev) > 0)
BIO_printf(out, "Revoked Certificates:\n");
else
BIO_printf(out, "No Revoked Certificates.\n");
for (i = 0; i < sk_X509_REVOKED_num(rev); i++) {
r = sk_X509_REVOKED_value(rev, i);
BIO_printf(out, " Serial Number: ");
i2a_ASN1_INTEGER(out, r->serialNumber);
BIO_printf(out, "\n Revocation Date: ");
ASN1_TIME_print(out, r->revocationDate);
BIO_printf(out, "\n");
X509V3_extensions_print(out, "CRL entry extensions",
r->extensions, 0, 8);
}
X509_signature_print(out, x->sig_alg, x->signature);
return 1;
}
@@ -0,0 +1,113 @@
/* crypto/asn1/t_pkey.c */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.]
*/
#include <stdio.h>
#include "cryptlib.h"
#include <openssl/objects.h>
#include <openssl/buffer.h>
#include <openssl/bn.h>
int ASN1_bn_print(BIO *bp, const char *number, const BIGNUM *num,
unsigned char *buf, int off)
{
int n, i;
const char *neg;
if (num == NULL)
return (1);
neg = (BN_is_negative(num)) ? "-" : "";
if (!BIO_indent(bp, off, 128))
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)num->d[0], neg,
(unsigned long)num->d[0])
<= 0)
return (0);
} else {
buf[0] = 0;
if (BIO_printf(bp, "%s%s", number,
(neg[0] == '-') ? " (Negative)" : "") <= 0)
return (0);
n = BN_bn2bin(num, &buf[1]);
if (buf[1] & 0x80)
n++;
else
buf++;
for (i = 0; i < n; i++) {
if ((i % 15) == 0) {
if (BIO_puts(bp, "\n") <= 0 || !BIO_indent(bp, off + 4, 128))
return 0;
}
if (BIO_printf(bp, "%02x%s", buf[i], ((i + 1) == n) ? "" : ":")
<= 0)
return (0);
}
if (BIO_write(bp, "\n", 1) <= 0)
return (0);
}
return (1);
}
@@ -0,0 +1,255 @@
/* crypto/asn1/t_req.c */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.]
*/
#include <stdio.h>
#include "cryptlib.h"
#include <openssl/buffer.h>
#include <openssl/bn.h>
#include <openssl/objects.h>
#include <openssl/x509.h>
#include <openssl/x509v3.h>
#ifndef OPENSSL_NO_RSA
# include <openssl/rsa.h>
#endif
#ifndef OPENSSL_NO_DSA
# include <openssl/dsa.h>
#endif
#ifndef OPENSSL_NO_FP_API
int X509_REQ_print_fp(FILE *fp, X509_REQ *x)
{
BIO *b;
int ret;
if ((b = BIO_new(BIO_s_file())) == NULL) {
X509err(X509_F_X509_REQ_PRINT_FP, ERR_R_BUF_LIB);
return (0);
}
BIO_set_fp(b, fp, BIO_NOCLOSE);
ret = X509_REQ_print(b, x);
BIO_free(b);
return (ret);
}
#endif
int X509_REQ_print_ex(BIO *bp, X509_REQ *x, unsigned long nmflags,
unsigned long cflag)
{
unsigned long l;
int i;
const char *neg;
X509_REQ_INFO *ri;
EVP_PKEY *pkey;
STACK_OF(X509_ATTRIBUTE) *sk;
STACK_OF(X509_EXTENSION) *exts;
char mlch = ' ';
int nmindent = 0;
if ((nmflags & XN_FLAG_SEP_MASK) == XN_FLAG_SEP_MULTILINE) {
mlch = '\n';
nmindent = 12;
}
if (nmflags == X509_FLAG_COMPAT)
nmindent = 16;
ri = x->req_info;
if (!(cflag & X509_FLAG_NO_HEADER)) {
if (BIO_write(bp, "Certificate Request:\n", 21) <= 0)
goto err;
if (BIO_write(bp, " Data:\n", 10) <= 0)
goto err;
}
if (!(cflag & X509_FLAG_NO_VERSION)) {
neg = (ri->version->type == V_ASN1_NEG_INTEGER) ? "-" : "";
l = 0;
for (i = 0; i < ri->version->length; i++) {
l <<= 8;
l += ri->version->data[i];
}
if (BIO_printf(bp, "%8sVersion: %s%lu (%s0x%lx)\n", "", neg, l, neg,
l) <= 0)
goto err;
}
if (!(cflag & X509_FLAG_NO_SUBJECT)) {
if (BIO_printf(bp, " Subject:%c", mlch) <= 0)
goto err;
if (X509_NAME_print_ex(bp, ri->subject, nmindent, nmflags) < 0)
goto err;
if (BIO_write(bp, "\n", 1) <= 0)
goto err;
}
if (!(cflag & X509_FLAG_NO_PUBKEY)) {
if (BIO_write(bp, " Subject Public Key Info:\n", 33) <= 0)
goto err;
if (BIO_printf(bp, "%12sPublic Key Algorithm: ", "") <= 0)
goto err;
if (i2a_ASN1_OBJECT(bp, ri->pubkey->algor->algorithm) <= 0)
goto err;
if (BIO_puts(bp, "\n") <= 0)
goto err;
pkey = X509_REQ_get_pubkey(x);
if (pkey == NULL) {
BIO_printf(bp, "%12sUnable to load Public Key\n", "");
ERR_print_errors(bp);
} else {
EVP_PKEY_print_public(bp, pkey, 16, NULL);
EVP_PKEY_free(pkey);
}
}
if (!(cflag & X509_FLAG_NO_ATTRIBUTES)) {
/* may not be */
if (BIO_printf(bp, "%8sAttributes:\n", "") <= 0)
goto err;
sk = x->req_info->attributes;
if (sk_X509_ATTRIBUTE_num(sk) == 0) {
if (BIO_printf(bp, "%12sa0:00\n", "") <= 0)
goto err;
} else {
for (i = 0; i < sk_X509_ATTRIBUTE_num(sk); i++) {
ASN1_TYPE *at;
X509_ATTRIBUTE *a;
ASN1_BIT_STRING *bs = NULL;
ASN1_TYPE *t;
int j, type = 0, count = 1, ii = 0;
a = sk_X509_ATTRIBUTE_value(sk, i);
if (X509_REQ_extension_nid(OBJ_obj2nid(a->object)))
continue;
if (BIO_printf(bp, "%12s", "") <= 0)
goto err;
if ((j = i2a_ASN1_OBJECT(bp, a->object)) > 0) {
if (a->single) {
t = a->value.single;
type = t->type;
bs = t->value.bit_string;
} else {
ii = 0;
count = sk_ASN1_TYPE_num(a->value.set);
get_next:
at = sk_ASN1_TYPE_value(a->value.set, ii);
type = at->type;
bs = at->value.asn1_string;
}
}
for (j = 25 - j; j > 0; j--)
if (BIO_write(bp, " ", 1) != 1)
goto err;
if (BIO_puts(bp, ":") <= 0)
goto err;
if ((type == V_ASN1_PRINTABLESTRING) ||
(type == V_ASN1_UTF8STRING) ||
(type == V_ASN1_T61STRING) ||
(type == V_ASN1_IA5STRING)) {
if (BIO_write(bp, (char *)bs->data, bs->length)
!= bs->length)
goto err;
BIO_puts(bp, "\n");
} else {
BIO_puts(bp, "unable to print attribute\n");
}
if (++ii < count)
goto get_next;
}
}
}
if (!(cflag & X509_FLAG_NO_EXTENSIONS)) {
exts = X509_REQ_get_extensions(x);
if (exts) {
BIO_printf(bp, "%8sRequested Extensions:\n", "");
for (i = 0; i < sk_X509_EXTENSION_num(exts); i++) {
ASN1_OBJECT *obj;
X509_EXTENSION *ex;
int j;
ex = sk_X509_EXTENSION_value(exts, i);
if (BIO_printf(bp, "%12s", "") <= 0)
goto err;
obj = X509_EXTENSION_get_object(ex);
i2a_ASN1_OBJECT(bp, obj);
j = X509_EXTENSION_get_critical(ex);
if (BIO_printf(bp, ": %s\n", j ? "critical" : "") <= 0)
goto err;
if (!X509V3_EXT_print(bp, ex, cflag, 16)) {
BIO_printf(bp, "%16s", "");
M_ASN1_OCTET_STRING_print(bp, ex->value);
}
if (BIO_write(bp, "\n", 1) <= 0)
goto err;
}
sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free);
}
}
if (!(cflag & X509_FLAG_NO_SIGDUMP)) {
if (!X509_signature_print(bp, x->sig_alg, x->signature))
goto err;
}
return (1);
err:
X509err(X509_F_X509_REQ_PRINT_EX, ERR_R_BUF_LIB);
return (0);
}
int X509_REQ_print(BIO *bp, X509_REQ *x)
{
return X509_REQ_print_ex(bp, x, XN_FLAG_COMPAT, X509_FLAG_COMPAT);
}
@@ -0,0 +1,108 @@
/* t_spki.c */
/*
* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
* 1999.
*/
/* ====================================================================
* Copyright (c) 1999-2021 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/x509.h>
#include <openssl/asn1.h>
#ifndef OPENSSL_NO_RSA
# include <openssl/rsa.h>
#endif
#ifndef OPENSSL_NO_DSA
# include <openssl/dsa.h>
#endif
#include <openssl/bn.h>
/* Print out an SPKI */
int NETSCAPE_SPKI_print(BIO *out, NETSCAPE_SPKI *spki)
{
EVP_PKEY *pkey;
ASN1_IA5STRING *chal;
int i, n;
char *s;
BIO_printf(out, "Netscape SPKI:\n");
i = OBJ_obj2nid(spki->spkac->pubkey->algor->algorithm);
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->length, 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;
}
@@ -0,0 +1,556 @@
/* crypto/asn1/t_x509.c */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.]
*/
#include <stdio.h>
#include "cryptlib.h"
#include <openssl/buffer.h>
#include <openssl/bn.h>
#ifndef OPENSSL_NO_RSA
# include <openssl/rsa.h>
#endif
#ifndef OPENSSL_NO_DSA
# include <openssl/dsa.h>
#endif
#ifndef OPENSSL_NO_EC
# include <openssl/ec.h>
#endif
#include <openssl/objects.h>
#include <openssl/x509.h>
#include <openssl/x509v3.h>
#include "asn1_locl.h"
#ifndef OPENSSL_NO_FP_API
int X509_print_fp(FILE *fp, X509 *x)
{
return X509_print_ex_fp(fp, x, XN_FLAG_COMPAT, X509_FLAG_COMPAT);
}
int X509_print_ex_fp(FILE *fp, X509 *x, unsigned long nmflag,
unsigned long cflag)
{
BIO *b;
int ret;
if ((b = BIO_new(BIO_s_file())) == NULL) {
X509err(X509_F_X509_PRINT_EX_FP, ERR_R_BUF_LIB);
return (0);
}
BIO_set_fp(b, fp, BIO_NOCLOSE);
ret = X509_print_ex(b, x, nmflag, cflag);
BIO_free(b);
return (ret);
}
#endif
int X509_print(BIO *bp, X509 *x)
{
return X509_print_ex(bp, x, XN_FLAG_COMPAT, X509_FLAG_COMPAT);
}
int X509_print_ex(BIO *bp, X509 *x, unsigned long nmflags,
unsigned long cflag)
{
long l;
int ret = 0, i;
char *m = NULL, mlch = ' ';
int nmindent = 0;
X509_CINF *ci;
ASN1_INTEGER *bs;
EVP_PKEY *pkey = NULL;
const char *neg;
if ((nmflags & XN_FLAG_SEP_MASK) == XN_FLAG_SEP_MULTILINE) {
mlch = '\n';
nmindent = 12;
}
if (nmflags == X509_FLAG_COMPAT)
nmindent = 16;
ci = x->cert_info;
if (!(cflag & X509_FLAG_NO_HEADER)) {
if (BIO_write(bp, "Certificate:\n", 13) <= 0)
goto err;
if (BIO_write(bp, " Data:\n", 10) <= 0)
goto err;
}
if (!(cflag & X509_FLAG_NO_VERSION)) {
l = X509_get_version(x);
if (BIO_printf(bp, "%8sVersion: %lu (0x%lx)\n", "", l + 1, l) <= 0)
goto err;
}
if (!(cflag & X509_FLAG_NO_SERIAL)) {
if (BIO_write(bp, " Serial Number:", 22) <= 0)
goto err;
bs = X509_get_serialNumber(x);
if (bs->length < (int)sizeof(long)
|| (bs->length == sizeof(long) && (bs->data[0] & 0x80) == 0)) {
l = ASN1_INTEGER_get(bs);
if (bs->type == V_ASN1_NEG_INTEGER) {
l = -l;
neg = "-";
} else
neg = "";
if (BIO_printf(bp, " %s%lu (%s0x%lx)\n", neg, l, neg, l) <= 0)
goto err;
} else {
neg = (bs->type == V_ASN1_NEG_INTEGER) ? " (Negative)" : "";
if (BIO_printf(bp, "\n%12s%s", "", neg) <= 0)
goto err;
for (i = 0; i < bs->length; i++) {
if (BIO_printf(bp, "%02x%c", bs->data[i],
((i + 1 == bs->length) ? '\n' : ':')) <= 0)
goto err;
}
}
}
if (!(cflag & X509_FLAG_NO_SIGNAME)) {
if (X509_signature_print(bp, ci->signature, NULL) <= 0)
goto err;
#if 0
if (BIO_printf(bp, "%8sSignature Algorithm: ", "") <= 0)
goto err;
if (i2a_ASN1_OBJECT(bp, ci->signature->algorithm) <= 0)
goto err;
if (BIO_puts(bp, "\n") <= 0)
goto err;
#endif
}
if (!(cflag & X509_FLAG_NO_ISSUER)) {
if (BIO_printf(bp, " Issuer:%c", mlch) <= 0)
goto err;
if (X509_NAME_print_ex(bp, X509_get_issuer_name(x), nmindent, nmflags)
< 0)
goto err;
if (BIO_write(bp, "\n", 1) <= 0)
goto err;
}
if (!(cflag & X509_FLAG_NO_VALIDITY)) {
if (BIO_write(bp, " Validity\n", 17) <= 0)
goto err;
if (BIO_write(bp, " Not Before: ", 24) <= 0)
goto err;
if (!ASN1_TIME_print(bp, X509_get_notBefore(x)))
goto err;
if (BIO_write(bp, "\n Not After : ", 25) <= 0)
goto err;
if (!ASN1_TIME_print(bp, X509_get_notAfter(x)))
goto err;
if (BIO_write(bp, "\n", 1) <= 0)
goto err;
}
if (!(cflag & X509_FLAG_NO_SUBJECT)) {
if (BIO_printf(bp, " Subject:%c", mlch) <= 0)
goto err;
if (X509_NAME_print_ex
(bp, X509_get_subject_name(x), nmindent, nmflags) < 0)
goto err;
if (BIO_write(bp, "\n", 1) <= 0)
goto err;
}
if (!(cflag & X509_FLAG_NO_PUBKEY)) {
if (BIO_write(bp, " Subject Public Key Info:\n", 33) <= 0)
goto err;
if (BIO_printf(bp, "%12sPublic Key Algorithm: ", "") <= 0)
goto err;
if (i2a_ASN1_OBJECT(bp, ci->key->algor->algorithm) <= 0)
goto err;
if (BIO_puts(bp, "\n") <= 0)
goto err;
pkey = X509_get_pubkey(x);
if (pkey == NULL) {
BIO_printf(bp, "%12sUnable to load Public Key\n", "");
ERR_print_errors(bp);
} else {
EVP_PKEY_print_public(bp, pkey, 16, NULL);
EVP_PKEY_free(pkey);
}
}
if (!(cflag & X509_FLAG_NO_IDS)) {
if (ci->issuerUID) {
if (BIO_printf(bp, "%8sIssuer Unique ID: ", "") <= 0)
goto err;
if (!X509_signature_dump(bp, ci->issuerUID, 12))
goto err;
}
if (ci->subjectUID) {
if (BIO_printf(bp, "%8sSubject Unique ID: ", "") <= 0)
goto err;
if (!X509_signature_dump(bp, ci->subjectUID, 12))
goto err;
}
}
if (!(cflag & X509_FLAG_NO_EXTENSIONS))
X509V3_extensions_print(bp, "X509v3 extensions",
ci->extensions, cflag, 8);
if (!(cflag & X509_FLAG_NO_SIGDUMP)) {
if (X509_signature_print(bp, x->sig_alg, x->signature) <= 0)
goto err;
}
if (!(cflag & X509_FLAG_NO_AUX)) {
if (!X509_CERT_AUX_print(bp, x->aux, 0))
goto err;
}
ret = 1;
err:
if (m != NULL)
OPENSSL_free(m);
return (ret);
}
int X509_ocspid_print(BIO *bp, X509 *x)
{
unsigned char *der = NULL;
unsigned char *dertmp;
int derlen;
int i;
unsigned char SHA1md[SHA_DIGEST_LENGTH];
/*
* display the hash of the subject as it would appear in OCSP requests
*/
if (BIO_printf(bp, " Subject OCSP hash: ") <= 0)
goto err;
derlen = i2d_X509_NAME(x->cert_info->subject, NULL);
if ((der = dertmp = (unsigned char *)OPENSSL_malloc(derlen)) == NULL)
goto err;
i2d_X509_NAME(x->cert_info->subject, &dertmp);
if (!EVP_Digest(der, derlen, SHA1md, NULL, EVP_sha1(), NULL))
goto err;
for (i = 0; i < SHA_DIGEST_LENGTH; i++) {
if (BIO_printf(bp, "%02X", SHA1md[i]) <= 0)
goto err;
}
OPENSSL_free(der);
der = NULL;
/*
* display the hash of the public key as it would appear in OCSP requests
*/
if (BIO_printf(bp, "\n Public key OCSP hash: ") <= 0)
goto err;
if (!EVP_Digest(x->cert_info->key->public_key->data,
x->cert_info->key->public_key->length,
SHA1md, NULL, EVP_sha1(), NULL))
goto err;
for (i = 0; i < SHA_DIGEST_LENGTH; i++) {
if (BIO_printf(bp, "%02X", SHA1md[i]) <= 0)
goto err;
}
BIO_printf(bp, "\n");
return (1);
err:
if (der != NULL)
OPENSSL_free(der);
return (0);
}
int X509_signature_dump(BIO *bp, const ASN1_STRING *sig, int indent)
{
const unsigned char *s;
int i, n;
n = sig->length;
s = sig->data;
for (i = 0; i < n; i++) {
if ((i % 18) == 0) {
if (BIO_write(bp, "\n", 1) <= 0)
return 0;
if (BIO_indent(bp, indent, indent) <= 0)
return 0;
}
if (BIO_printf(bp, "%02x%s", s[i], ((i + 1) == n) ? "" : ":") <= 0)
return 0;
}
if (BIO_write(bp, "\n", 1) != 1)
return 0;
return 1;
}
int X509_signature_print(BIO *bp, X509_ALGOR *sigalg, ASN1_STRING *sig)
{
int sig_nid;
if (BIO_puts(bp, " Signature Algorithm: ") <= 0)
return 0;
if (i2a_ASN1_OBJECT(bp, sigalg->algorithm) <= 0)
return 0;
sig_nid = OBJ_obj2nid(sigalg->algorithm);
if (sig_nid != NID_undef) {
int pkey_nid, dig_nid;
const EVP_PKEY_ASN1_METHOD *ameth;
if (OBJ_find_sigid_algs(sig_nid, &dig_nid, &pkey_nid)) {
ameth = EVP_PKEY_asn1_find(NULL, pkey_nid);
if (ameth && ameth->sig_print)
return ameth->sig_print(bp, sigalg, sig, 9, 0);
}
}
if (sig)
return X509_signature_dump(bp, sig, 9);
else if (BIO_puts(bp, "\n") <= 0)
return 0;
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);
}
int ASN1_TIME_print(BIO *bp, const ASN1_TIME *tm)
{
if (tm->type == V_ASN1_UTCTIME)
return ASN1_UTCTIME_print(bp, tm);
if (tm->type == V_ASN1_GENERALIZEDTIME)
return ASN1_GENERALIZEDTIME_print(bp, tm);
BIO_write(bp, "Bad time value", 14);
return (0);
}
static const char *mon[12] = {
"Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
};
int ASN1_GENERALIZEDTIME_print(BIO *bp, const ASN1_GENERALIZEDTIME *tm)
{
char *v;
int gmt = 0;
int i;
int y = 0, M = 0, d = 0, h = 0, m = 0, s = 0;
char *f = NULL;
int f_len = 0;
i = tm->length;
v = (char *)tm->data;
if (i < 12)
goto err;
if (v[i - 1] == 'Z')
gmt = 1;
for (i = 0; i < 12; i++)
if ((v[i] > '9') || (v[i] < '0'))
goto err;
y = (v[0] - '0') * 1000 + (v[1] - '0') * 100
+ (v[2] - '0') * 10 + (v[3] - '0');
M = (v[4] - '0') * 10 + (v[5] - '0');
if ((M > 12) || (M < 1))
goto err;
d = (v[6] - '0') * 10 + (v[7] - '0');
h = (v[8] - '0') * 10 + (v[9] - '0');
m = (v[10] - '0') * 10 + (v[11] - '0');
if (tm->length >= 14 &&
(v[12] >= '0') && (v[12] <= '9') &&
(v[13] >= '0') && (v[13] <= '9')) {
s = (v[12] - '0') * 10 + (v[13] - '0');
/* Check for fractions of seconds. */
if (tm->length >= 15 && v[14] == '.') {
int l = tm->length;
f = &v[14]; /* The decimal point. */
f_len = 1;
while (14 + f_len < l && f[f_len] >= '0' && f[f_len] <= '9')
++f_len;
}
}
if (BIO_printf(bp, "%s %2d %02d:%02d:%02d%.*s %d%s",
mon[M - 1], d, h, m, s, f_len, f, y,
(gmt) ? " GMT" : "") <= 0)
return (0);
else
return (1);
err:
BIO_write(bp, "Bad time value", 14);
return (0);
}
int ASN1_UTCTIME_print(BIO *bp, const ASN1_UTCTIME *tm)
{
const char *v;
int gmt = 0;
int i;
int y = 0, M = 0, d = 0, h = 0, m = 0, s = 0;
i = tm->length;
v = (const char *)tm->data;
if (i < 10)
goto err;
if (v[i - 1] == 'Z')
gmt = 1;
for (i = 0; i < 10; i++)
if ((v[i] > '9') || (v[i] < '0'))
goto err;
y = (v[0] - '0') * 10 + (v[1] - '0');
if (y < 50)
y += 100;
M = (v[2] - '0') * 10 + (v[3] - '0');
if ((M > 12) || (M < 1))
goto err;
d = (v[4] - '0') * 10 + (v[5] - '0');
h = (v[6] - '0') * 10 + (v[7] - '0');
m = (v[8] - '0') * 10 + (v[9] - '0');
if (tm->length >= 12 &&
(v[10] >= '0') && (v[10] <= '9') && (v[11] >= '0') && (v[11] <= '9'))
s = (v[10] - '0') * 10 + (v[11] - '0');
if (BIO_printf(bp, "%s %2d %02d:%02d:%02d %d%s",
mon[M - 1], d, h, m, s, y + 1900,
(gmt) ? " GMT" : "") <= 0)
return (0);
else
return (1);
err:
BIO_write(bp, "Bad time value", 14);
return (0);
}
int X509_NAME_print(BIO *bp, X509_NAME *name, int obase)
{
char *s, *c, *b;
int ret = 0, l, i;
l = 80 - 2 - obase;
b = X509_NAME_oneline(name, NULL, 0);
if (!b)
return 0;
if (!*b) {
OPENSSL_free(b);
return 1;
}
s = b + 1; /* skip the first slash */
c = s;
for (;;) {
#ifndef CHARSET_EBCDIC
if (((*s == '/') &&
((s[1] >= 'A') && (s[1] <= 'Z') && ((s[2] == '=') ||
((s[2] >= 'A')
&& (s[2] <= 'Z')
&& (s[3] == '='))
))) || (*s == '\0'))
#else
if (((*s == '/') &&
(isupper(s[1]) && ((s[2] == '=') ||
(isupper(s[2]) && (s[3] == '='))
))) || (*s == '\0'))
#endif
{
i = s - c;
if (BIO_write(bp, c, i) != i)
goto err;
c = s + 1; /* skip following slash */
if (*s != '\0') {
if (BIO_write(bp, ", ", 2) != 2)
goto err;
}
l--;
}
if (*s == '\0')
break;
s++;
l--;
}
ret = 1;
if (0) {
err:
X509err(X509_F_X509_NAME_PRINT, ERR_R_BUF_LIB);
}
OPENSSL_free(b);
return (ret);
}
@@ -0,0 +1,116 @@
/* t_x509a.c */
/*
* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
* 1999.
*/
/* ====================================================================
* Copyright (c) 1999-2021 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/evp.h>
#include <openssl/asn1.h>
#include <openssl/x509.h>
/*
* X509_CERT_AUX and string set routines
*/
int X509_CERT_AUX_print(BIO *out, X509_CERT_AUX *aux, int indent)
{
char oidstr[80], first;
int i;
if (!aux)
return 1;
if (aux->trust) {
first = 1;
BIO_printf(out, "%*sTrusted Uses:\n%*s", indent, "", indent + 2, "");
for (i = 0; i < sk_ASN1_OBJECT_num(aux->trust); i++) {
if (!first)
BIO_puts(out, ", ");
else
first = 0;
OBJ_obj2txt(oidstr, sizeof(oidstr),
sk_ASN1_OBJECT_value(aux->trust, i), 0);
BIO_puts(out, oidstr);
}
BIO_puts(out, "\n");
} else
BIO_printf(out, "%*sNo Trusted Uses.\n", indent, "");
if (aux->reject) {
first = 1;
BIO_printf(out, "%*sRejected Uses:\n%*s", indent, "", indent + 2, "");
for (i = 0; i < sk_ASN1_OBJECT_num(aux->reject); i++) {
if (!first)
BIO_puts(out, ", ");
else
first = 0;
OBJ_obj2txt(oidstr, sizeof(oidstr),
sk_ASN1_OBJECT_value(aux->reject, i), 0);
BIO_puts(out, oidstr);
}
BIO_puts(out, "\n");
} else
BIO_printf(out, "%*sNo Rejected Uses.\n", indent, "");
if (aux->alias)
BIO_printf(out, "%*sAlias: %.*s\n", indent, "", aux->alias->length,
aux->alias->data);
if (aux->keyid) {
BIO_printf(out, "%*sKey Id: ", indent, "");
for (i = 0; i < aux->keyid->length; i++)
BIO_printf(out, "%s%02X", i ? ":" : "", aux->keyid->data[i]);
BIO_write(out, "\n", 1);
}
return 1;
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,685 @@
/* tasn_enc.c */
/*
* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
* 2000.
*/
/* ====================================================================
* Copyright (c) 2000-2020 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 <stddef.h>
#include <string.h>
#include <limits.h>
#include "cryptlib.h"
#include <openssl/asn1.h>
#include <openssl/asn1t.h>
#include <openssl/objects.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);
/*
* 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;
buf = OPENSSL_malloc(len);
if (!buf)
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;
unsigned char *p = NULL;
int i, seqcontlen, seqlen, ndef = 1;
const ASN1_COMPAT_FUNCS *cf;
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);
break;
case ASN1_ITYPE_MSTRING:
/*
* It never makes sense for multi-strings to have implicit tagging, so
* if tag != -1, then this looks like an error in the template.
*/
if (tag != -1) {
ASN1err(ASN1_F_ASN1_ITEM_EX_I2D, ASN1_R_BAD_TEMPLATE);
return -1;
}
return asn1_i2d_ex_primitive(pval, out, it, -1, aclass);
case ASN1_ITYPE_CHOICE:
/*
* It never makes sense for CHOICE types to have implicit tagging, so
* if tag != -1, then this looks like an error in the template.
*/
if (tag != -1) {
ASN1err(ASN1_F_ASN1_ITEM_EX_I2D, ASN1_R_BAD_TEMPLATE);
return -1;
}
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_COMPAT:
/* old style hackery... */
cf = it->funcs;
if (out)
p = *out;
i = cf->asn1_i2d(*pval, out);
/*
* Fixup for IMPLICIT tag: note this messes up for tags > 30, but so
* did the old code. Tags > 30 are very rare anyway.
*/
if (out && (tag != -1))
*p = aclass | tag | (*p & V_ASN1_CONSTRUCTED);
return i;
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;
}
int ASN1_template_i2d(ASN1_VALUE **pval, unsigned char **out,
const ASN1_TEMPLATE *tt)
{
return asn1_template_ex_i2d(pval, out, tt, -1, 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;
flags = tt->flags;
/*
* 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)
return 0;
tmpdat = OPENSSL_malloc(skcontlen);
if (!tmpdat) {
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 */
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);
break;
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);
break;
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;
}
@@ -0,0 +1,246 @@
/* tasn_fre.c */
/*
* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
* 2000.
*/
/* ====================================================================
* Copyright (c) 2000 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 <stddef.h>
#include <openssl/asn1.h>
#include <openssl/asn1t.h>
#include <openssl/objects.h>
#include "asn1_int.h"
/* Free up an ASN1 structure */
void ASN1_item_free(ASN1_VALUE *val, const ASN1_ITEM *it)
{
asn1_item_combine_free(&val, it, 0);
}
void ASN1_item_ex_free(ASN1_VALUE **pval, const ASN1_ITEM *it)
{
asn1_item_combine_free(pval, it, 0);
}
void asn1_item_combine_free(ASN1_VALUE **pval, const ASN1_ITEM *it, int combine)
{
const ASN1_TEMPLATE *tt = NULL, *seqtt;
const ASN1_EXTERN_FUNCS *ef;
const ASN1_COMPAT_FUNCS *cf;
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);
break;
case ASN1_ITYPE_MSTRING:
ASN1_primitive_free(pval, it);
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 (!combine) {
OPENSSL_free(*pval);
*pval = NULL;
}
break;
case ASN1_ITYPE_COMPAT:
cf = it->funcs;
if (cf && cf->asn1_free)
cf->asn1_free(*pval);
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)
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 wont be able to determine the type of the field it
* defines. So free up in reverse order.
*/
tt = it->templates + it->tcount - 1;
for (i = 0; i < it->tcount; tt--, i++) {
ASN1_VALUE **pseqval;
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 (!combine) {
OPENSSL_free(*pval);
*pval = NULL;
}
break;
}
}
void ASN1_template_free(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt)
{
int i;
if (tt->flags & ASN1_TFLG_SK_MASK) {
STACK_OF(ASN1_VALUE) *sk = (STACK_OF(ASN1_VALUE) *)*pval;
for (i = 0; i < sk_ASN1_VALUE_num(sk); i++) {
ASN1_VALUE *vtmp;
vtmp = sk_ASN1_VALUE_value(sk, i);
asn1_item_combine_free(&vtmp, ASN1_ITEM_ptr(tt->item), 0);
}
sk_ASN1_VALUE_free(sk);
*pval = NULL;
} else
asn1_item_combine_free(pval, ASN1_ITEM_ptr(tt->item),
tt->flags & ASN1_TFLG_COMBINE);
}
void ASN1_primitive_free(ASN1_VALUE **pval, const ASN1_ITEM *it)
{
int utype;
if (it) {
const ASN1_PRIMITIVE_FUNCS *pf;
pf = it->funcs;
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);
OPENSSL_free(*pval);
break;
default:
ASN1_STRING_free((ASN1_STRING *)*pval);
*pval = NULL;
break;
}
*pval = NULL;
}
@@ -0,0 +1,385 @@
/* tasn_new.c */
/*
* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
* 2000.
*/
/* ====================================================================
* Copyright (c) 2000-2004 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 <stddef.h>
#include <openssl/asn1.h>
#include <openssl/objects.h>
#include <openssl/err.h>
#include <openssl/asn1t.h>
#include <string.h>
#include "asn1_int.h"
static int asn1_item_ex_combine_new(ASN1_VALUE **pval, const ASN1_ITEM *it,
int combine);
static void asn1_item_clear(ASN1_VALUE **pval, const ASN1_ITEM *it);
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_ex_combine_new(pval, it, 0);
}
static int asn1_item_ex_combine_new(ASN1_VALUE **pval, const ASN1_ITEM *it,
int combine)
{
const ASN1_TEMPLATE *tt = NULL;
const ASN1_COMPAT_FUNCS *cf;
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;
#ifdef CRYPTO_MDEBUG
if (it->sname)
CRYPTO_push_info(it->sname);
#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_COMPAT:
cf = it->funcs;
if (cf && cf->asn1_new) {
*pval = cf->asn1_new();
if (!*pval)
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))
goto memerr;
break;
case ASN1_ITYPE_MSTRING:
if (!ASN1_primitive_new(pval, it))
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) {
#ifdef CRYPTO_MDEBUG
if (it->sname)
CRYPTO_pop_info();
#endif
return 1;
}
}
if (!combine) {
*pval = OPENSSL_malloc(it->size);
if (!*pval)
goto memerr;
memset(*pval, 0, it->size);
}
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) {
#ifdef CRYPTO_MDEBUG
if (it->sname)
CRYPTO_pop_info();
#endif
return 1;
}
}
if (!combine) {
*pval = OPENSSL_malloc(it->size);
if (!*pval)
goto memerr;
memset(*pval, 0, it->size);
asn1_do_lock(pval, 0, it);
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;
}
#ifdef CRYPTO_MDEBUG
if (it->sname)
CRYPTO_pop_info();
#endif
return 1;
memerr2:
asn1_item_combine_free(pval, it, combine);
memerr:
ASN1err(ASN1_F_ASN1_ITEM_EX_COMBINE_NEW, ERR_R_MALLOC_FAILURE);
#ifdef CRYPTO_MDEBUG
if (it->sname)
CRYPTO_pop_info();
#endif
return 0;
auxerr2:
asn1_item_combine_free(pval, it, combine);
auxerr:
ASN1err(ASN1_F_ASN1_ITEM_EX_COMBINE_NEW, ASN1_R_AUX_ERROR);
#ifdef CRYPTO_MDEBUG
if (it->sname)
CRYPTO_pop_info();
#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_COMPAT:
case ASN1_ITYPE_CHOICE:
case ASN1_ITYPE_SEQUENCE:
case ASN1_ITYPE_NDEF_SEQUENCE:
*pval = NULL;
break;
}
}
int ASN1_template_new(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt)
{
const ASN1_ITEM *it = ASN1_ITEM_ptr(tt->item);
int ret;
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;
}
#ifdef CRYPTO_MDEBUG
if (tt->field_name)
CRYPTO_push_info(tt->field_name);
#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_ex_combine_new(pval, it, tt->flags & ASN1_TFLG_COMBINE);
done:
#ifdef CRYPTO_MDEBUG
if (it->sname)
CRYPTO_pop_info();
#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.
*/
int ASN1_primitive_new(ASN1_VALUE **pval, const ASN1_ITEM *it)
{
ASN1_TYPE *typ;
ASN1_STRING *str;
int utype;
if (!it)
return 0;
if (it->funcs) {
const ASN1_PRIMITIVE_FUNCS *pf = it->funcs;
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:
typ = OPENSSL_malloc(sizeof(ASN1_TYPE));
if (!typ)
return 0;
typ->value.ptr = NULL;
typ->type = -1;
*pval = (ASN1_VALUE *)typ;
break;
default:
str = ASN1_STRING_type_new(utype);
if (it->itype == ASN1_ITYPE_MSTRING && str)
str->flags |= ASN1_STRING_FLAG_MSTRING;
*pval = (ASN1_VALUE *)str;
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;
}
@@ -0,0 +1,593 @@
/* tasn_prn.c */
/*
* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
* 2000.
*/
/* ====================================================================
* Copyright (c) 2000,2005 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 <stddef.h>
#include "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"
/*
* Print routines.
*/
/* ASN1_PCTX routines */
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_malloc(sizeof(ASN1_PCTX));
if (ret == NULL) {
ASN1err(ASN1_F_ASN1_PCTX_NEW, ERR_R_MALLOC_FAILURE);
return NULL;
}
ret->flags = 0;
ret->nm_flags = 0;
ret->cert_flags = 0;
ret->oid_flags = 0;
ret->str_flags = 0;
return ret;
}
void ASN1_PCTX_free(ASN1_PCTX *p)
{
OPENSSL_free(p);
}
unsigned long ASN1_PCTX_get_flags(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(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(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(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(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);
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 thru */
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:
#if 0
if (!nohdr && !asn1_print_fsname(out, indent, fname, sname, pctx))
return 0;
#endif
/* 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;
}
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;
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 (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 && BIO_printf(out, "%*s<EMPTY>\n", indent + 2, "") <= 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 char spaces[] = " ";
const int nspaces = sizeof(spaces) - 1;
#if 0
if (!sname && !fname)
return 1;
#endif
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_ctx(BIO *out, int boolval,
const ASN1_PCTX *pctx)
{
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_ctx(BIO *out, ASN1_INTEGER *str,
const ASN1_PCTX *pctx)
{
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_ctx(BIO *out, const ASN1_OBJECT *oid,
const ASN1_PCTX *pctx)
{
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_ctx(BIO *out, ASN1_STRING *str, int indent,
const ASN1_PCTX *pctx)
{
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, (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_ctx(out, boolval, pctx);
}
break;
case V_ASN1_INTEGER:
case V_ASN1_ENUMERATED:
ret = asn1_print_integer_ctx(out, str, pctx);
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_ctx(out, (const ASN1_OBJECT *)*fld, pctx);
break;
case V_ASN1_OCTET_STRING:
case V_ASN1_BIT_STRING:
ret = asn1_print_obstring_ctx(out, str, indent, pctx);
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;
}
@@ -0,0 +1,149 @@
/* tasn_typ.c */
/*
* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
* 2000.
*/
/* ====================================================================
* Copyright (c) 2000 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 <openssl/asn1.h>
#include <openssl/asn1t.h>
/* Declarations for string types */
IMPLEMENT_ASN1_TYPE(ASN1_INTEGER)
IMPLEMENT_ASN1_FUNCTIONS(ASN1_INTEGER)
IMPLEMENT_ASN1_TYPE(ASN1_ENUMERATED)
IMPLEMENT_ASN1_FUNCTIONS(ASN1_ENUMERATED)
IMPLEMENT_ASN1_TYPE(ASN1_BIT_STRING)
IMPLEMENT_ASN1_FUNCTIONS(ASN1_BIT_STRING)
IMPLEMENT_ASN1_TYPE(ASN1_OCTET_STRING)
IMPLEMENT_ASN1_FUNCTIONS(ASN1_OCTET_STRING)
IMPLEMENT_ASN1_TYPE(ASN1_NULL)
IMPLEMENT_ASN1_FUNCTIONS(ASN1_NULL)
IMPLEMENT_ASN1_TYPE(ASN1_OBJECT)
IMPLEMENT_ASN1_TYPE(ASN1_UTF8STRING)
IMPLEMENT_ASN1_FUNCTIONS(ASN1_UTF8STRING)
IMPLEMENT_ASN1_TYPE(ASN1_PRINTABLESTRING)
IMPLEMENT_ASN1_FUNCTIONS(ASN1_PRINTABLESTRING)
IMPLEMENT_ASN1_TYPE(ASN1_T61STRING)
IMPLEMENT_ASN1_FUNCTIONS(ASN1_T61STRING)
IMPLEMENT_ASN1_TYPE(ASN1_IA5STRING)
IMPLEMENT_ASN1_FUNCTIONS(ASN1_IA5STRING)
IMPLEMENT_ASN1_TYPE(ASN1_GENERALSTRING)
IMPLEMENT_ASN1_FUNCTIONS(ASN1_GENERALSTRING)
IMPLEMENT_ASN1_TYPE(ASN1_UTCTIME)
IMPLEMENT_ASN1_FUNCTIONS(ASN1_UTCTIME)
IMPLEMENT_ASN1_TYPE(ASN1_GENERALIZEDTIME)
IMPLEMENT_ASN1_FUNCTIONS(ASN1_GENERALIZEDTIME)
IMPLEMENT_ASN1_TYPE(ASN1_VISIBLESTRING)
IMPLEMENT_ASN1_FUNCTIONS(ASN1_VISIBLESTRING)
IMPLEMENT_ASN1_TYPE(ASN1_UNIVERSALSTRING)
IMPLEMENT_ASN1_FUNCTIONS(ASN1_UNIVERSALSTRING)
IMPLEMENT_ASN1_TYPE(ASN1_BMPSTRING)
IMPLEMENT_ASN1_FUNCTIONS(ASN1_BMPSTRING)
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)
@@ -0,0 +1,275 @@
/* tasn_utl.c */
/*
* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
* 2000.
*/
/* ====================================================================
* Copyright (c) 2000-2004 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 <stddef.h>
#include <string.h>
#include <openssl/asn1.h>
#include <openssl/asn1t.h>
#include <openssl/objects.h>
#include <openssl/err.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 reference counting. The value 'op' decides what to do. if it is +1
* then the count is incremented. If op is 0 count is set to 1. If op is -1
* count is decremented and the return value is the current refrence count or
* 0 if no reference count exists.
*/
int asn1_do_lock(ASN1_VALUE **pval, int op, const ASN1_ITEM *it)
{
const ASN1_AUX *aux;
int *lck, ret;
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);
if (op == 0) {
*lck = 1;
return 1;
}
ret = CRYPTO_add(lck, op, aux->ref_lock);
#ifdef REF_PRINT
fprintf(stderr, "%s: Reference Count: %d\n", it->sname, *lck);
#endif
#ifdef REF_CHECK
if (ret < 0)
fprintf(stderr, "%s, bad reference count\n", it->sname);
#endif
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) {
if (enc->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;
if (enc->enc)
OPENSSL_free(enc->enc);
enc->enc = OPENSSL_malloc(inlen);
if (!enc->enc)
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;
if (tt->flags & ASN1_TFLG_COMBINE)
return pval;
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);
/*
* 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;
}
@@ -0,0 +1,148 @@
/* x_algor.c */
/*
* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
* 2000.
*/
/* ====================================================================
* Copyright (c) 2000 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 <stddef.h>
#include <openssl/x509.h>
#include <openssl/asn1.h>
#include <openssl/asn1t.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)
IMPLEMENT_STACK_OF(X509_ALGOR)
IMPLEMENT_ASN1_SET_OF(X509_ALGOR)
int X509_ALGOR_set0(X509_ALGOR *alg, ASN1_OBJECT *aobj, int ptype, void *pval)
{
if (!alg)
return 0;
if (ptype != V_ASN1_UNDEF) {
if (alg->parameter == NULL)
alg->parameter = ASN1_TYPE_new();
if (alg->parameter == NULL)
return 0;
}
if (alg) {
if (alg->algorithm)
ASN1_OBJECT_free(alg->algorithm);
alg->algorithm = aobj;
}
if (ptype == 0)
return 1;
if (ptype == V_ASN1_UNDEF) {
if (alg->parameter) {
ASN1_TYPE_free(alg->parameter);
alg->parameter = NULL;
}
} else
ASN1_TYPE_set(alg->parameter, ptype, pval);
return 1;
}
void X509_ALGOR_get0(ASN1_OBJECT **paobj, int *pptype, void **ppval,
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);
}
@@ -0,0 +1,125 @@
/* crypto/asn1/x_attrib.c */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.]
*/
#include <stdio.h>
#include <stddef.h>
#include "cryptlib.h"
#include <openssl/objects.h>
#include <openssl/asn1t.h>
#include <openssl/x509.h>
/*-
* X509_ATTRIBUTE: this has the following form:
*
* typedef struct x509_attributes_st
* {
* ASN1_OBJECT *object;
* int single;
* union {
* char *ptr;
* STACK_OF(ASN1_TYPE) *set;
* ASN1_TYPE *single;
* } value;
* } X509_ATTRIBUTE;
*
* this needs some extra thought because the CHOICE type is
* merged with the main structure and because the value can
* be anything at all we *must* try the SET OF first because
* the ASN1_ANY type will swallow anything including the whole
* SET OF structure.
*/
ASN1_CHOICE(X509_ATTRIBUTE_SET) = {
ASN1_SET_OF(X509_ATTRIBUTE, value.set, ASN1_ANY),
ASN1_SIMPLE(X509_ATTRIBUTE, value.single, ASN1_ANY)
} ASN1_CHOICE_END_selector(X509_ATTRIBUTE, X509_ATTRIBUTE_SET, single)
ASN1_SEQUENCE(X509_ATTRIBUTE) = {
ASN1_SIMPLE(X509_ATTRIBUTE, object, ASN1_OBJECT),
/* CHOICE type merged with parent */
ASN1_EX_COMBINE(0, 0, X509_ATTRIBUTE_SET)
} ASN1_SEQUENCE_END(X509_ATTRIBUTE)
IMPLEMENT_ASN1_FUNCTIONS(X509_ATTRIBUTE)
IMPLEMENT_ASN1_DUP_FUNCTION(X509_ATTRIBUTE)
X509_ATTRIBUTE *X509_ATTRIBUTE_create(int nid, int atrtype, void *value)
{
X509_ATTRIBUTE *ret = NULL;
ASN1_TYPE *val = NULL;
if ((ret = X509_ATTRIBUTE_new()) == NULL)
return (NULL);
ret->object = OBJ_nid2obj(nid);
ret->single = 0;
if ((ret->value.set = sk_ASN1_TYPE_new_null()) == NULL)
goto err;
if ((val = ASN1_TYPE_new()) == NULL)
goto err;
if (!sk_ASN1_TYPE_push(ret->value.set, val))
goto err;
ASN1_TYPE_set(val, atrtype, value);
return (ret);
err:
if (ret != NULL)
X509_ATTRIBUTE_free(ret);
if (val != NULL)
ASN1_TYPE_free(val);
return (NULL);
}

Some files were not shown because too many files have changed in this diff Show More