1
0
Fork 0
mirror of https://github.com/ossrs/srs.git synced 2025-03-09 15:49:59 +00:00

Upgrade openssl from 1.1.0e to 1.1.1b, with source code. 4.0.78

This commit is contained in:
winlin 2021-03-01 20:47:57 +08:00
parent 8f1c992379
commit 96dbd7bced
1476 changed files with 616554 additions and 4 deletions

View file

@ -0,0 +1,56 @@
/*
* Copyright 2004-2016 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
/*
* This file is dual-licensed and is also available under the following
* terms:
*
* 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;
}

View file

@ -0,0 +1,169 @@
/*
* Copyright 2004-2018 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
/*
* This file is dual-licensed and is also available under the following
* terms:
*
* Copyright (c) 2004, 2018, 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 COPYRIGHT HOLDERS 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 COPYRIGHT
* OWNER 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.
*/
#include <stddef.h>
#include <stdlib.h>
#include <limits.h>
#include <string.h>
#include <sys/types.h>
#include <dirent.h>
#include <errno.h>
#ifndef LPDIR_H
# include "LPdir.h"
#endif
#ifdef __VMS
# include <ctype.h>
#endif
/*
* The POSIX macro for the maximum number of characters in a file path is
* NAME_MAX. However, some operating systems use PATH_MAX instead.
* Therefore, it seems natural to first check for PATH_MAX and use that, and
* if it doesn't exist, use NAME_MAX.
*/
#if defined(PATH_MAX)
# define LP_ENTRY_SIZE PATH_MAX
#elif defined(NAME_MAX)
# define LP_ENTRY_SIZE NAME_MAX
#endif
/*
* Of course, there's the possibility that neither PATH_MAX nor NAME_MAX
* exist. It's also possible that NAME_MAX exists but is define to a very
* small value (HP-UX offers 14), so we need to check if we got a result, and
* if it meets a minimum standard, and create or change it if not.
*/
#if !defined(LP_ENTRY_SIZE) || LP_ENTRY_SIZE<255
# undef LP_ENTRY_SIZE
# define LP_ENTRY_SIZE 255
#endif
struct LP_dir_context_st {
DIR *dir;
char entry_name[LP_ENTRY_SIZE + 1];
#ifdef __VMS
int expect_file_generations;
char previous_entry_name[LP_ENTRY_SIZE + 1];
#endif
};
const char *LP_find_file(LP_DIR_CTX **ctx, const char *directory)
{
struct dirent *direntry = NULL;
if (ctx == NULL || directory == NULL) {
errno = EINVAL;
return 0;
}
errno = 0;
if (*ctx == NULL) {
*ctx = malloc(sizeof(**ctx));
if (*ctx == NULL) {
errno = ENOMEM;
return 0;
}
memset(*ctx, 0, sizeof(**ctx));
#ifdef __VMS
{
char c = directory[strlen(directory) - 1];
if (c == ']' || c == '>' || c == ':')
(*ctx)->expect_file_generations = 1;
}
#endif
(*ctx)->dir = opendir(directory);
if ((*ctx)->dir == NULL) {
int save_errno = errno; /* Probably not needed, but I'm paranoid */
free(*ctx);
*ctx = NULL;
errno = save_errno;
return 0;
}
}
#ifdef __VMS
strncpy((*ctx)->previous_entry_name, (*ctx)->entry_name,
sizeof((*ctx)->previous_entry_name));
again:
#endif
direntry = readdir((*ctx)->dir);
if (direntry == NULL) {
return 0;
}
strncpy((*ctx)->entry_name, direntry->d_name,
sizeof((*ctx)->entry_name) - 1);
(*ctx)->entry_name[sizeof((*ctx)->entry_name) - 1] = '\0';
#ifdef __VMS
if ((*ctx)->expect_file_generations) {
char *p = (*ctx)->entry_name + strlen((*ctx)->entry_name);
while(p > (*ctx)->entry_name && isdigit(p[-1]))
p--;
if (p > (*ctx)->entry_name && p[-1] == ';')
p[-1] = '\0';
if (strcasecmp((*ctx)->entry_name, (*ctx)->previous_entry_name) == 0)
goto again;
}
#endif
return (*ctx)->entry_name;
}
int LP_find_file_end(LP_DIR_CTX **ctx)
{
if (ctx != NULL && *ctx != NULL) {
int ret = closedir((*ctx)->dir);
free(*ctx);
switch (ret) {
case 0:
return 1;
case -1:
return 0;
default:
break;
}
}
errno = EINVAL;
return 0;
}

View file

@ -0,0 +1,207 @@
/*
* Copyright 2004-2016 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
/*
* This file is dual-licensed and is also available under the following
* terms:
*
* 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 COPYRIGHT HOLDERS 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 COPYRIGHT
* OWNER 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.
*/
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <descrip.h>
#include <namdef.h>
#include <rmsdef.h>
#include <libfildef.h>
#include <lib$routines.h>
#include <strdef.h>
#include <str$routines.h>
#include <stsdef.h>
#ifndef LPDIR_H
# include "LPdir.h"
#endif
#include "vms_rms.h"
/* Some compiler options hide EVMSERR. */
#ifndef EVMSERR
# define EVMSERR 65535 /* error for non-translatable VMS errors */
#endif
struct LP_dir_context_st {
unsigned long VMS_context;
char filespec[NAMX_MAXRSS + 1];
char result[NAMX_MAXRSS + 1];
struct dsc$descriptor_d filespec_dsc;
struct dsc$descriptor_d result_dsc;
};
const char *LP_find_file(LP_DIR_CTX **ctx, const char *directory)
{
int status;
char *p, *r;
size_t l;
unsigned long flags = 0;
/* Arrange 32-bit pointer to (copied) string storage, if needed. */
#if __INITIAL_POINTER_SIZE == 64
# pragma pointer_size save
# pragma pointer_size 32
char *ctx_filespec_32p;
# pragma pointer_size restore
char ctx_filespec_32[NAMX_MAXRSS + 1];
#endif /* __INITIAL_POINTER_SIZE == 64 */
#ifdef NAML$C_MAXRSS
flags |= LIB$M_FIL_LONG_NAMES;
#endif
if (ctx == NULL || directory == NULL) {
errno = EINVAL;
return 0;
}
errno = 0;
if (*ctx == NULL) {
size_t filespeclen = strlen(directory);
char *filespec = NULL;
if (filespeclen == 0) {
errno = ENOENT;
return 0;
}
/* MUST be a VMS directory specification! Let's estimate if it is. */
if (directory[filespeclen - 1] != ']'
&& directory[filespeclen - 1] != '>'
&& directory[filespeclen - 1] != ':') {
errno = EINVAL;
return 0;
}
filespeclen += 4; /* "*.*;" */
if (filespeclen > NAMX_MAXRSS) {
errno = ENAMETOOLONG;
return 0;
}
*ctx = malloc(sizeof(**ctx));
if (*ctx == NULL) {
errno = ENOMEM;
return 0;
}
memset(*ctx, 0, sizeof(**ctx));
strcpy((*ctx)->filespec, directory);
strcat((*ctx)->filespec, "*.*;");
/* Arrange 32-bit pointer to (copied) string storage, if needed. */
#if __INITIAL_POINTER_SIZE == 64
# define CTX_FILESPEC ctx_filespec_32p
/* Copy the file name to storage with a 32-bit pointer. */
ctx_filespec_32p = ctx_filespec_32;
strcpy(ctx_filespec_32p, (*ctx)->filespec);
#else /* __INITIAL_POINTER_SIZE == 64 */
# define CTX_FILESPEC (*ctx)->filespec
#endif /* __INITIAL_POINTER_SIZE == 64 [else] */
(*ctx)->filespec_dsc.dsc$w_length = filespeclen;
(*ctx)->filespec_dsc.dsc$b_dtype = DSC$K_DTYPE_T;
(*ctx)->filespec_dsc.dsc$b_class = DSC$K_CLASS_S;
(*ctx)->filespec_dsc.dsc$a_pointer = CTX_FILESPEC;
}
(*ctx)->result_dsc.dsc$w_length = 0;
(*ctx)->result_dsc.dsc$b_dtype = DSC$K_DTYPE_T;
(*ctx)->result_dsc.dsc$b_class = DSC$K_CLASS_D;
(*ctx)->result_dsc.dsc$a_pointer = 0;
status = lib$find_file(&(*ctx)->filespec_dsc, &(*ctx)->result_dsc,
&(*ctx)->VMS_context, 0, 0, 0, &flags);
if (status == RMS$_NMF) {
errno = 0;
vaxc$errno = status;
return NULL;
}
if (!$VMS_STATUS_SUCCESS(status)) {
errno = EVMSERR;
vaxc$errno = status;
return NULL;
}
/*
* Quick, cheap and dirty way to discard any device and directory, since
* we only want file names
*/
l = (*ctx)->result_dsc.dsc$w_length;
p = (*ctx)->result_dsc.dsc$a_pointer;
r = p;
for (; *p; p++) {
if (*p == '^' && p[1] != '\0') { /* Take care of ODS-5 escapes */
p++;
} else if (*p == ':' || *p == '>' || *p == ']') {
l -= p + 1 - r;
r = p + 1;
} else if (*p == ';') {
l = p - r;
break;
}
}
strncpy((*ctx)->result, r, l);
(*ctx)->result[l] = '\0';
str$free1_dx(&(*ctx)->result_dsc);
return (*ctx)->result;
}
int LP_find_file_end(LP_DIR_CTX **ctx)
{
if (ctx != NULL && *ctx != NULL) {
int status = lib$find_file_end(&(*ctx)->VMS_context);
free(*ctx);
if (!$VMS_STATUS_SUCCESS(status)) {
errno = EVMSERR;
vaxc$errno = status;
return 0;
}
return 1;
}
errno = EINVAL;
return 0;
}

View file

@ -0,0 +1,214 @@
/*
* Copyright 2004-2016 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
/*
* This file is dual-licensed and is also available under the following
* terms:
*
* 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 COPYRIGHT HOLDERS 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 COPYRIGHT
* OWNER 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.
*/
#include <windows.h>
#include <tchar.h>
#include "internal/numbers.h"
#ifndef LPDIR_H
# include "LPdir.h"
#endif
/*
* We're most likely overcautious here, but let's reserve for broken WinCE
* headers and explicitly opt for UNICODE call. Keep in mind that our WinCE
* builds are compiled with -DUNICODE [as well as -D_UNICODE].
*/
#if defined(LP_SYS_WINCE) && !defined(FindFirstFile)
# define FindFirstFile FindFirstFileW
#endif
#if defined(LP_SYS_WINCE) && !defined(FindNextFile)
# define FindNextFile FindNextFileW
#endif
#ifndef NAME_MAX
# define NAME_MAX 255
#endif
#ifdef CP_UTF8
# define CP_DEFAULT CP_UTF8
#else
# define CP_DEFAULT CP_ACP
#endif
struct LP_dir_context_st {
WIN32_FIND_DATA ctx;
HANDLE handle;
char entry_name[NAME_MAX + 1];
};
const char *LP_find_file(LP_DIR_CTX **ctx, const char *directory)
{
if (ctx == NULL || directory == NULL) {
errno = EINVAL;
return 0;
}
errno = 0;
if (*ctx == NULL) {
size_t dirlen = strlen(directory);
if (dirlen == 0 || dirlen > INT_MAX - 3) {
errno = ENOENT;
return 0;
}
*ctx = malloc(sizeof(**ctx));
if (*ctx == NULL) {
errno = ENOMEM;
return 0;
}
memset(*ctx, 0, sizeof(**ctx));
if (sizeof(TCHAR) != sizeof(char)) {
TCHAR *wdir = NULL;
/* len_0 denotes string length *with* trailing 0 */
size_t index = 0, len_0 = dirlen + 1;
#ifdef LP_MULTIBYTE_AVAILABLE
int sz = 0;
UINT cp;
do {
# ifdef CP_UTF8
if ((sz = MultiByteToWideChar((cp = CP_UTF8), 0,
directory, len_0,
NULL, 0)) > 0 ||
GetLastError() != ERROR_NO_UNICODE_TRANSLATION)
break;
# endif
sz = MultiByteToWideChar((cp = CP_ACP), 0,
directory, len_0,
NULL, 0);
} while (0);
if (sz > 0) {
/*
* allocate two additional characters in case we need to
* concatenate asterisk, |sz| covers trailing '\0'!
*/
wdir = _alloca((sz + 2) * sizeof(TCHAR));
if (!MultiByteToWideChar(cp, 0, directory, len_0,
(WCHAR *)wdir, sz)) {
free(*ctx);
*ctx = NULL;
errno = EINVAL;
return 0;
}
} else
#endif
{
sz = len_0;
/*
* allocate two additional characters in case we need to
* concatenate asterisk, |sz| covers trailing '\0'!
*/
wdir = _alloca((sz + 2) * sizeof(TCHAR));
for (index = 0; index < len_0; index++)
wdir[index] = (TCHAR)directory[index];
}
sz--; /* wdir[sz] is trailing '\0' now */
if (wdir[sz - 1] != TEXT('*')) {
if (wdir[sz - 1] != TEXT('/') && wdir[sz - 1] != TEXT('\\'))
_tcscpy(wdir + sz, TEXT("/*"));
else
_tcscpy(wdir + sz, TEXT("*"));
}
(*ctx)->handle = FindFirstFile(wdir, &(*ctx)->ctx);
} else {
if (directory[dirlen - 1] != '*') {
char *buf = _alloca(dirlen + 3);
strcpy(buf, directory);
if (buf[dirlen - 1] != '/' && buf[dirlen - 1] != '\\')
strcpy(buf + dirlen, "/*");
else
strcpy(buf + dirlen, "*");
directory = buf;
}
(*ctx)->handle = FindFirstFile((TCHAR *)directory, &(*ctx)->ctx);
}
if ((*ctx)->handle == INVALID_HANDLE_VALUE) {
free(*ctx);
*ctx = NULL;
errno = EINVAL;
return 0;
}
} else {
if (FindNextFile((*ctx)->handle, &(*ctx)->ctx) == FALSE) {
return 0;
}
}
if (sizeof(TCHAR) != sizeof(char)) {
TCHAR *wdir = (*ctx)->ctx.cFileName;
size_t index, len_0 = 0;
while (wdir[len_0] && len_0 < (sizeof((*ctx)->entry_name) - 1))
len_0++;
len_0++;
#ifdef LP_MULTIBYTE_AVAILABLE
if (!WideCharToMultiByte(CP_DEFAULT, 0, (WCHAR *)wdir, len_0,
(*ctx)->entry_name,
sizeof((*ctx)->entry_name), NULL, 0))
#endif
for (index = 0; index < len_0; index++)
(*ctx)->entry_name[index] = (char)wdir[index];
} else
strncpy((*ctx)->entry_name, (const char *)(*ctx)->ctx.cFileName,
sizeof((*ctx)->entry_name) - 1);
(*ctx)->entry_name[sizeof((*ctx)->entry_name) - 1] = '\0';
return (*ctx)->entry_name;
}
int LP_find_file_end(LP_DIR_CTX **ctx)
{
if (ctx != NULL && *ctx != NULL) {
FindClose((*ctx)->handle);
free(*ctx);
*ctx = NULL;
return 1;
}
errno = EINVAL;
return 0;
}

View file

@ -0,0 +1,41 @@
/*
* Copyright 2004-2016 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
/*
* This file is dual-licensed and is also available under the following
* terms:
*
* 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 COPYRIGHT HOLDERS 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 COPYRIGHT
* OWNER 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.
*/
#define LP_SYS_WIN32
#define LP_MULTIBYTE_AVAILABLE
#include "LPdir_win.c"

View file

@ -0,0 +1,44 @@
/*
* Copyright 2004-2016 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
/*
* This file is dual-licensed and is also available under the following
* terms:
*
* 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 COPYRIGHT HOLDERS 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 COPYRIGHT
* OWNER 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.
*/
#define LP_SYS_WINCE
/*
* We might want to define LP_MULTIBYTE_AVAILABLE here. It's currently under
* investigation what the exact conditions would be
*/
#include "LPdir_win.c"

View file

@ -0,0 +1,24 @@
/*
* Copyright 2002-2016 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <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);
}

View file

@ -0,0 +1,43 @@
/*
* Copyright 2002-2016 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <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

View file

@ -0,0 +1,26 @@
/*
* Copyright 2002-2016 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <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);
}

View file

@ -0,0 +1,284 @@
/*
* Copyright 2006-2016 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include "internal/cryptlib.h"
#include <openssl/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;
if (length == 0)
return;
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;
}
}
}

View file

@ -0,0 +1,42 @@
/*
* Copyright 2002-2016 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#ifndef HEADER_AES_LOCL_H
# define HEADER_AES_LOCL_H
# include <openssl/e_os2.h>
# 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 */

View file

@ -0,0 +1,21 @@
/*
* Copyright 2002-2016 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <openssl/opensslv.h>
#include <openssl/aes.h>
#include "aes_locl.h"
const char *AES_options(void)
{
#ifdef FULL_UNROLL
return "aes(full)";
#else
return "aes(partial)";
#endif
}

View file

@ -0,0 +1,19 @@
/*
* Copyright 2002-2016 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <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);
}

View file

@ -0,0 +1,27 @@
/*
* Copyright 2008-2016 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include "internal/cryptlib.h"
#include <openssl/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

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

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

View file

@ -0,0 +1,929 @@
#! /usr/bin/env perl
# Copyright 2012-2016 The OpenSSL Project Authors. All Rights Reserved.
#
# Licensed under the OpenSSL license (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
# ====================================================================
# Written by David S. Miller and Andy Polyakov.
# The module is licensed under 2-clause BSD license. October 2012.
# All rights reserved.
# ====================================================================
######################################################################
# AES for SPARC T4.
#
# AES round instructions complete in 3 cycles and can be issued every
# cycle. It means that round calculations should take 4*rounds cycles,
# because any given round instruction depends on result of *both*
# previous instructions:
#
# |0 |1 |2 |3 |4
# |01|01|01|
# |23|23|23|
# |01|01|...
# |23|...
#
# Provided that fxor [with IV] takes 3 cycles to complete, critical
# path length for CBC encrypt would be 3+4*rounds, or in other words
# it should process one byte in at least (3+4*rounds)/16 cycles. This
# estimate doesn't account for "collateral" instructions, such as
# fetching input from memory, xor-ing it with zero-round key and
# storing the result. Yet, *measured* performance [for data aligned
# at 64-bit boundary!] deviates from this equation by less than 0.5%:
#
# 128-bit key 192- 256-
# CBC encrypt 2.70/2.90(*) 3.20/3.40 3.70/3.90
# (*) numbers after slash are for
# misaligned data.
#
# Out-of-order execution logic managed to fully overlap "collateral"
# instructions with those on critical path. Amazing!
#
# As with Intel AES-NI, question is if it's possible to improve
# performance of parallelizable modes by interleaving round
# instructions. Provided round instruction latency and throughput
# optimal interleave factor is 2. But can we expect 2x performance
# improvement? Well, as round instructions can be issued one per
# cycle, they don't saturate the 2-way issue pipeline and therefore
# there is room for "collateral" calculations... Yet, 2x speed-up
# over CBC encrypt remains unattaintable:
#
# 128-bit key 192- 256-
# CBC decrypt 1.64/2.11 1.89/2.37 2.23/2.61
# CTR 1.64/2.08(*) 1.89/2.33 2.23/2.61
# (*) numbers after slash are for
# misaligned data.
#
# Estimates based on amount of instructions under assumption that
# round instructions are not pairable with any other instruction
# suggest that latter is the actual case and pipeline runs
# underutilized. It should be noted that T4 out-of-order execution
# logic is so capable that performance gain from 2x interleave is
# not even impressive, ~7-13% over non-interleaved code, largest
# for 256-bit keys.
# To anchor to something else, software implementation processes
# one byte in 29 cycles with 128-bit key on same processor. Intel
# Sandy Bridge encrypts byte in 5.07 cycles in CBC mode and decrypts
# in 0.93, naturally with AES-NI.
$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
push(@INC,"${dir}","${dir}../../perlasm");
require "sparcv9_modes.pl";
$output = pop;
open STDOUT,">$output";
$::evp=1; # if $evp is set to 0, script generates module with
# AES_[en|de]crypt, AES_set_[en|de]crypt_key and AES_cbc_encrypt entry
# points. These however are not fully compatible with openssl/aes.h,
# because they expect AES_KEY to be aligned at 64-bit boundary. When
# used through EVP, alignment is arranged at EVP layer. Second thing
# that is arranged by EVP is at least 32-bit alignment of IV.
######################################################################
# single-round subroutines
#
{
my ($inp,$out,$key,$rounds,$tmp,$mask)=map("%o$_",(0..5));
$code.=<<___;
#include "sparc_arch.h"
#ifdef __arch64__
.register %g2,#scratch
.register %g3,#scratch
#endif
.text
.globl aes_t4_encrypt
.align 32
aes_t4_encrypt:
andcc $inp, 7, %g1 ! is input aligned?
andn $inp, 7, $inp
ldx [$key + 0], %g4
ldx [$key + 8], %g5
ldx [$inp + 0], %o4
bz,pt %icc, 1f
ldx [$inp + 8], %o5
ldx [$inp + 16], $inp
sll %g1, 3, %g1
sub %g0, %g1, %o3
sllx %o4, %g1, %o4
sllx %o5, %g1, %g1
srlx %o5, %o3, %o5
srlx $inp, %o3, %o3
or %o5, %o4, %o4
or %o3, %g1, %o5
1:
ld [$key + 240], $rounds
ldd [$key + 16], %f12
ldd [$key + 24], %f14
xor %g4, %o4, %o4
xor %g5, %o5, %o5
movxtod %o4, %f0
movxtod %o5, %f2
srl $rounds, 1, $rounds
ldd [$key + 32], %f16
sub $rounds, 1, $rounds
ldd [$key + 40], %f18
add $key, 48, $key
.Lenc:
aes_eround01 %f12, %f0, %f2, %f4
aes_eround23 %f14, %f0, %f2, %f2
ldd [$key + 0], %f12
ldd [$key + 8], %f14
sub $rounds,1,$rounds
aes_eround01 %f16, %f4, %f2, %f0
aes_eround23 %f18, %f4, %f2, %f2
ldd [$key + 16], %f16
ldd [$key + 24], %f18
brnz,pt $rounds, .Lenc
add $key, 32, $key
andcc $out, 7, $tmp ! is output aligned?
aes_eround01 %f12, %f0, %f2, %f4
aes_eround23 %f14, %f0, %f2, %f2
aes_eround01_l %f16, %f4, %f2, %f0
aes_eround23_l %f18, %f4, %f2, %f2
bnz,pn %icc, 2f
nop
std %f0, [$out + 0]
retl
std %f2, [$out + 8]
2: alignaddrl $out, %g0, $out
mov 0xff, $mask
srl $mask, $tmp, $mask
faligndata %f0, %f0, %f4
faligndata %f0, %f2, %f6
faligndata %f2, %f2, %f8
stda %f4, [$out + $mask]0xc0 ! partial store
std %f6, [$out + 8]
add $out, 16, $out
orn %g0, $mask, $mask
retl
stda %f8, [$out + $mask]0xc0 ! partial store
.type aes_t4_encrypt,#function
.size aes_t4_encrypt,.-aes_t4_encrypt
.globl aes_t4_decrypt
.align 32
aes_t4_decrypt:
andcc $inp, 7, %g1 ! is input aligned?
andn $inp, 7, $inp
ldx [$key + 0], %g4
ldx [$key + 8], %g5
ldx [$inp + 0], %o4
bz,pt %icc, 1f
ldx [$inp + 8], %o5
ldx [$inp + 16], $inp
sll %g1, 3, %g1
sub %g0, %g1, %o3
sllx %o4, %g1, %o4
sllx %o5, %g1, %g1
srlx %o5, %o3, %o5
srlx $inp, %o3, %o3
or %o5, %o4, %o4
or %o3, %g1, %o5
1:
ld [$key + 240], $rounds
ldd [$key + 16], %f12
ldd [$key + 24], %f14
xor %g4, %o4, %o4
xor %g5, %o5, %o5
movxtod %o4, %f0
movxtod %o5, %f2
srl $rounds, 1, $rounds
ldd [$key + 32], %f16
sub $rounds, 1, $rounds
ldd [$key + 40], %f18
add $key, 48, $key
.Ldec:
aes_dround01 %f12, %f0, %f2, %f4
aes_dround23 %f14, %f0, %f2, %f2
ldd [$key + 0], %f12
ldd [$key + 8], %f14
sub $rounds,1,$rounds
aes_dround01 %f16, %f4, %f2, %f0
aes_dround23 %f18, %f4, %f2, %f2
ldd [$key + 16], %f16
ldd [$key + 24], %f18
brnz,pt $rounds, .Ldec
add $key, 32, $key
andcc $out, 7, $tmp ! is output aligned?
aes_dround01 %f12, %f0, %f2, %f4
aes_dround23 %f14, %f0, %f2, %f2
aes_dround01_l %f16, %f4, %f2, %f0
aes_dround23_l %f18, %f4, %f2, %f2
bnz,pn %icc, 2f
nop
std %f0, [$out + 0]
retl
std %f2, [$out + 8]
2: alignaddrl $out, %g0, $out
mov 0xff, $mask
srl $mask, $tmp, $mask
faligndata %f0, %f0, %f4
faligndata %f0, %f2, %f6
faligndata %f2, %f2, %f8
stda %f4, [$out + $mask]0xc0 ! partial store
std %f6, [$out + 8]
add $out, 16, $out
orn %g0, $mask, $mask
retl
stda %f8, [$out + $mask]0xc0 ! partial store
.type aes_t4_decrypt,#function
.size aes_t4_decrypt,.-aes_t4_decrypt
___
}
######################################################################
# key setup subroutines
#
{
my ($inp,$bits,$out,$tmp)=map("%o$_",(0..5));
$code.=<<___;
.globl aes_t4_set_encrypt_key
.align 32
aes_t4_set_encrypt_key:
.Lset_encrypt_key:
and $inp, 7, $tmp
alignaddr $inp, %g0, $inp
cmp $bits, 192
ldd [$inp + 0], %f0
bl,pt %icc,.L128
ldd [$inp + 8], %f2
be,pt %icc,.L192
ldd [$inp + 16], %f4
brz,pt $tmp, .L256aligned
ldd [$inp + 24], %f6
ldd [$inp + 32], %f8
faligndata %f0, %f2, %f0
faligndata %f2, %f4, %f2
faligndata %f4, %f6, %f4
faligndata %f6, %f8, %f6
.L256aligned:
___
for ($i=0; $i<6; $i++) {
$code.=<<___;
std %f0, [$out + `32*$i+0`]
aes_kexpand1 %f0, %f6, $i, %f0
std %f2, [$out + `32*$i+8`]
aes_kexpand2 %f2, %f0, %f2
std %f4, [$out + `32*$i+16`]
aes_kexpand0 %f4, %f2, %f4
std %f6, [$out + `32*$i+24`]
aes_kexpand2 %f6, %f4, %f6
___
}
$code.=<<___;
std %f0, [$out + `32*$i+0`]
aes_kexpand1 %f0, %f6, $i, %f0
std %f2, [$out + `32*$i+8`]
aes_kexpand2 %f2, %f0, %f2
std %f4, [$out + `32*$i+16`]
std %f6, [$out + `32*$i+24`]
std %f0, [$out + `32*$i+32`]
std %f2, [$out + `32*$i+40`]
mov 14, $tmp
st $tmp, [$out + 240]
retl
xor %o0, %o0, %o0
.align 16
.L192:
brz,pt $tmp, .L192aligned
nop
ldd [$inp + 24], %f6
faligndata %f0, %f2, %f0
faligndata %f2, %f4, %f2
faligndata %f4, %f6, %f4
.L192aligned:
___
for ($i=0; $i<7; $i++) {
$code.=<<___;
std %f0, [$out + `24*$i+0`]
aes_kexpand1 %f0, %f4, $i, %f0
std %f2, [$out + `24*$i+8`]
aes_kexpand2 %f2, %f0, %f2
std %f4, [$out + `24*$i+16`]
aes_kexpand2 %f4, %f2, %f4
___
}
$code.=<<___;
std %f0, [$out + `24*$i+0`]
aes_kexpand1 %f0, %f4, $i, %f0
std %f2, [$out + `24*$i+8`]
aes_kexpand2 %f2, %f0, %f2
std %f4, [$out + `24*$i+16`]
std %f0, [$out + `24*$i+24`]
std %f2, [$out + `24*$i+32`]
mov 12, $tmp
st $tmp, [$out + 240]
retl
xor %o0, %o0, %o0
.align 16
.L128:
brz,pt $tmp, .L128aligned
nop
ldd [$inp + 16], %f4
faligndata %f0, %f2, %f0
faligndata %f2, %f4, %f2
.L128aligned:
___
for ($i=0; $i<10; $i++) {
$code.=<<___;
std %f0, [$out + `16*$i+0`]
aes_kexpand1 %f0, %f2, $i, %f0
std %f2, [$out + `16*$i+8`]
aes_kexpand2 %f2, %f0, %f2
___
}
$code.=<<___;
std %f0, [$out + `16*$i+0`]
std %f2, [$out + `16*$i+8`]
mov 10, $tmp
st $tmp, [$out + 240]
retl
xor %o0, %o0, %o0
.type aes_t4_set_encrypt_key,#function
.size aes_t4_set_encrypt_key,.-aes_t4_set_encrypt_key
.globl aes_t4_set_decrypt_key
.align 32
aes_t4_set_decrypt_key:
mov %o7, %o5
call .Lset_encrypt_key
nop
mov %o5, %o7
sll $tmp, 4, $inp ! $tmp is number of rounds
add $tmp, 2, $tmp
add $out, $inp, $inp ! $inp=$out+16*rounds
srl $tmp, 2, $tmp ! $tmp=(rounds+2)/4
.Lkey_flip:
ldd [$out + 0], %f0
ldd [$out + 8], %f2
ldd [$out + 16], %f4
ldd [$out + 24], %f6
ldd [$inp + 0], %f8
ldd [$inp + 8], %f10
ldd [$inp - 16], %f12
ldd [$inp - 8], %f14
sub $tmp, 1, $tmp
std %f0, [$inp + 0]
std %f2, [$inp + 8]
std %f4, [$inp - 16]
std %f6, [$inp - 8]
std %f8, [$out + 0]
std %f10, [$out + 8]
std %f12, [$out + 16]
std %f14, [$out + 24]
add $out, 32, $out
brnz $tmp, .Lkey_flip
sub $inp, 32, $inp
retl
xor %o0, %o0, %o0
.type aes_t4_set_decrypt_key,#function
.size aes_t4_set_decrypt_key,.-aes_t4_set_decrypt_key
___
}
{{{
my ($inp,$out,$len,$key,$ivec,$enc)=map("%i$_",(0..5));
my ($ileft,$iright,$ooff,$omask,$ivoff)=map("%l$_",(1..7));
$code.=<<___;
.align 32
_aes128_encrypt_1x:
___
for ($i=0; $i<4; $i++) {
$code.=<<___;
aes_eround01 %f`16+8*$i+0`, %f0, %f2, %f4
aes_eround23 %f`16+8*$i+2`, %f0, %f2, %f2
aes_eround01 %f`16+8*$i+4`, %f4, %f2, %f0
aes_eround23 %f`16+8*$i+6`, %f4, %f2, %f2
___
}
$code.=<<___;
aes_eround01 %f48, %f0, %f2, %f4
aes_eround23 %f50, %f0, %f2, %f2
aes_eround01_l %f52, %f4, %f2, %f0
retl
aes_eround23_l %f54, %f4, %f2, %f2
.type _aes128_encrypt_1x,#function
.size _aes128_encrypt_1x,.-_aes128_encrypt_1x
.align 32
_aes128_encrypt_2x:
___
for ($i=0; $i<4; $i++) {
$code.=<<___;
aes_eround01 %f`16+8*$i+0`, %f0, %f2, %f8
aes_eround23 %f`16+8*$i+2`, %f0, %f2, %f2
aes_eround01 %f`16+8*$i+0`, %f4, %f6, %f10
aes_eround23 %f`16+8*$i+2`, %f4, %f6, %f6
aes_eround01 %f`16+8*$i+4`, %f8, %f2, %f0
aes_eround23 %f`16+8*$i+6`, %f8, %f2, %f2
aes_eround01 %f`16+8*$i+4`, %f10, %f6, %f4
aes_eround23 %f`16+8*$i+6`, %f10, %f6, %f6
___
}
$code.=<<___;
aes_eround01 %f48, %f0, %f2, %f8
aes_eround23 %f50, %f0, %f2, %f2
aes_eround01 %f48, %f4, %f6, %f10
aes_eround23 %f50, %f4, %f6, %f6
aes_eround01_l %f52, %f8, %f2, %f0
aes_eround23_l %f54, %f8, %f2, %f2
aes_eround01_l %f52, %f10, %f6, %f4
retl
aes_eround23_l %f54, %f10, %f6, %f6
.type _aes128_encrypt_2x,#function
.size _aes128_encrypt_2x,.-_aes128_encrypt_2x
.align 32
_aes128_loadkey:
ldx [$key + 0], %g4
ldx [$key + 8], %g5
___
for ($i=2; $i<22;$i++) { # load key schedule
$code.=<<___;
ldd [$key + `8*$i`], %f`12+2*$i`
___
}
$code.=<<___;
retl
nop
.type _aes128_loadkey,#function
.size _aes128_loadkey,.-_aes128_loadkey
_aes128_load_enckey=_aes128_loadkey
_aes128_load_deckey=_aes128_loadkey
___
&alg_cbc_encrypt_implement("aes",128);
if ($::evp) {
&alg_ctr32_implement("aes",128);
&alg_xts_implement("aes",128,"en");
&alg_xts_implement("aes",128,"de");
}
&alg_cbc_decrypt_implement("aes",128);
$code.=<<___;
.align 32
_aes128_decrypt_1x:
___
for ($i=0; $i<4; $i++) {
$code.=<<___;
aes_dround01 %f`16+8*$i+0`, %f0, %f2, %f4
aes_dround23 %f`16+8*$i+2`, %f0, %f2, %f2
aes_dround01 %f`16+8*$i+4`, %f4, %f2, %f0
aes_dround23 %f`16+8*$i+6`, %f4, %f2, %f2
___
}
$code.=<<___;
aes_dround01 %f48, %f0, %f2, %f4
aes_dround23 %f50, %f0, %f2, %f2
aes_dround01_l %f52, %f4, %f2, %f0
retl
aes_dround23_l %f54, %f4, %f2, %f2
.type _aes128_decrypt_1x,#function
.size _aes128_decrypt_1x,.-_aes128_decrypt_1x
.align 32
_aes128_decrypt_2x:
___
for ($i=0; $i<4; $i++) {
$code.=<<___;
aes_dround01 %f`16+8*$i+0`, %f0, %f2, %f8
aes_dround23 %f`16+8*$i+2`, %f0, %f2, %f2
aes_dround01 %f`16+8*$i+0`, %f4, %f6, %f10
aes_dround23 %f`16+8*$i+2`, %f4, %f6, %f6
aes_dround01 %f`16+8*$i+4`, %f8, %f2, %f0
aes_dround23 %f`16+8*$i+6`, %f8, %f2, %f2
aes_dround01 %f`16+8*$i+4`, %f10, %f6, %f4
aes_dround23 %f`16+8*$i+6`, %f10, %f6, %f6
___
}
$code.=<<___;
aes_dround01 %f48, %f0, %f2, %f8
aes_dround23 %f50, %f0, %f2, %f2
aes_dround01 %f48, %f4, %f6, %f10
aes_dround23 %f50, %f4, %f6, %f6
aes_dround01_l %f52, %f8, %f2, %f0
aes_dround23_l %f54, %f8, %f2, %f2
aes_dround01_l %f52, %f10, %f6, %f4
retl
aes_dround23_l %f54, %f10, %f6, %f6
.type _aes128_decrypt_2x,#function
.size _aes128_decrypt_2x,.-_aes128_decrypt_2x
___
$code.=<<___;
.align 32
_aes192_encrypt_1x:
___
for ($i=0; $i<5; $i++) {
$code.=<<___;
aes_eround01 %f`16+8*$i+0`, %f0, %f2, %f4
aes_eround23 %f`16+8*$i+2`, %f0, %f2, %f2
aes_eround01 %f`16+8*$i+4`, %f4, %f2, %f0
aes_eround23 %f`16+8*$i+6`, %f4, %f2, %f2
___
}
$code.=<<___;
aes_eround01 %f56, %f0, %f2, %f4
aes_eround23 %f58, %f0, %f2, %f2
aes_eround01_l %f60, %f4, %f2, %f0
retl
aes_eround23_l %f62, %f4, %f2, %f2
.type _aes192_encrypt_1x,#function
.size _aes192_encrypt_1x,.-_aes192_encrypt_1x
.align 32
_aes192_encrypt_2x:
___
for ($i=0; $i<5; $i++) {
$code.=<<___;
aes_eround01 %f`16+8*$i+0`, %f0, %f2, %f8
aes_eround23 %f`16+8*$i+2`, %f0, %f2, %f2
aes_eround01 %f`16+8*$i+0`, %f4, %f6, %f10
aes_eround23 %f`16+8*$i+2`, %f4, %f6, %f6
aes_eround01 %f`16+8*$i+4`, %f8, %f2, %f0
aes_eround23 %f`16+8*$i+6`, %f8, %f2, %f2
aes_eround01 %f`16+8*$i+4`, %f10, %f6, %f4
aes_eround23 %f`16+8*$i+6`, %f10, %f6, %f6
___
}
$code.=<<___;
aes_eround01 %f56, %f0, %f2, %f8
aes_eround23 %f58, %f0, %f2, %f2
aes_eround01 %f56, %f4, %f6, %f10
aes_eround23 %f58, %f4, %f6, %f6
aes_eround01_l %f60, %f8, %f2, %f0
aes_eround23_l %f62, %f8, %f2, %f2
aes_eround01_l %f60, %f10, %f6, %f4
retl
aes_eround23_l %f62, %f10, %f6, %f6
.type _aes192_encrypt_2x,#function
.size _aes192_encrypt_2x,.-_aes192_encrypt_2x
.align 32
_aes256_encrypt_1x:
aes_eround01 %f16, %f0, %f2, %f4
aes_eround23 %f18, %f0, %f2, %f2
ldd [$key + 208], %f16
ldd [$key + 216], %f18
aes_eround01 %f20, %f4, %f2, %f0
aes_eround23 %f22, %f4, %f2, %f2
ldd [$key + 224], %f20
ldd [$key + 232], %f22
___
for ($i=1; $i<6; $i++) {
$code.=<<___;
aes_eround01 %f`16+8*$i+0`, %f0, %f2, %f4
aes_eround23 %f`16+8*$i+2`, %f0, %f2, %f2
aes_eround01 %f`16+8*$i+4`, %f4, %f2, %f0
aes_eround23 %f`16+8*$i+6`, %f4, %f2, %f2
___
}
$code.=<<___;
aes_eround01 %f16, %f0, %f2, %f4
aes_eround23 %f18, %f0, %f2, %f2
ldd [$key + 16], %f16
ldd [$key + 24], %f18
aes_eround01_l %f20, %f4, %f2, %f0
aes_eround23_l %f22, %f4, %f2, %f2
ldd [$key + 32], %f20
retl
ldd [$key + 40], %f22
.type _aes256_encrypt_1x,#function
.size _aes256_encrypt_1x,.-_aes256_encrypt_1x
.align 32
_aes256_encrypt_2x:
aes_eround01 %f16, %f0, %f2, %f8
aes_eround23 %f18, %f0, %f2, %f2
aes_eround01 %f16, %f4, %f6, %f10
aes_eround23 %f18, %f4, %f6, %f6
ldd [$key + 208], %f16
ldd [$key + 216], %f18
aes_eround01 %f20, %f8, %f2, %f0
aes_eround23 %f22, %f8, %f2, %f2
aes_eround01 %f20, %f10, %f6, %f4
aes_eround23 %f22, %f10, %f6, %f6
ldd [$key + 224], %f20
ldd [$key + 232], %f22
___
for ($i=1; $i<6; $i++) {
$code.=<<___;
aes_eround01 %f`16+8*$i+0`, %f0, %f2, %f8
aes_eround23 %f`16+8*$i+2`, %f0, %f2, %f2
aes_eround01 %f`16+8*$i+0`, %f4, %f6, %f10
aes_eround23 %f`16+8*$i+2`, %f4, %f6, %f6
aes_eround01 %f`16+8*$i+4`, %f8, %f2, %f0
aes_eround23 %f`16+8*$i+6`, %f8, %f2, %f2
aes_eround01 %f`16+8*$i+4`, %f10, %f6, %f4
aes_eround23 %f`16+8*$i+6`, %f10, %f6, %f6
___
}
$code.=<<___;
aes_eround01 %f16, %f0, %f2, %f8
aes_eround23 %f18, %f0, %f2, %f2
aes_eround01 %f16, %f4, %f6, %f10
aes_eround23 %f18, %f4, %f6, %f6
ldd [$key + 16], %f16
ldd [$key + 24], %f18
aes_eround01_l %f20, %f8, %f2, %f0
aes_eround23_l %f22, %f8, %f2, %f2
aes_eround01_l %f20, %f10, %f6, %f4
aes_eround23_l %f22, %f10, %f6, %f6
ldd [$key + 32], %f20
retl
ldd [$key + 40], %f22
.type _aes256_encrypt_2x,#function
.size _aes256_encrypt_2x,.-_aes256_encrypt_2x
.align 32
_aes192_loadkey:
ldx [$key + 0], %g4
ldx [$key + 8], %g5
___
for ($i=2; $i<26;$i++) { # load key schedule
$code.=<<___;
ldd [$key + `8*$i`], %f`12+2*$i`
___
}
$code.=<<___;
retl
nop
.type _aes192_loadkey,#function
.size _aes192_loadkey,.-_aes192_loadkey
_aes256_loadkey=_aes192_loadkey
_aes192_load_enckey=_aes192_loadkey
_aes192_load_deckey=_aes192_loadkey
_aes256_load_enckey=_aes192_loadkey
_aes256_load_deckey=_aes192_loadkey
___
&alg_cbc_encrypt_implement("aes",256);
&alg_cbc_encrypt_implement("aes",192);
if ($::evp) {
&alg_ctr32_implement("aes",256);
&alg_xts_implement("aes",256,"en");
&alg_xts_implement("aes",256,"de");
&alg_ctr32_implement("aes",192);
}
&alg_cbc_decrypt_implement("aes",192);
&alg_cbc_decrypt_implement("aes",256);
$code.=<<___;
.align 32
_aes256_decrypt_1x:
aes_dround01 %f16, %f0, %f2, %f4
aes_dround23 %f18, %f0, %f2, %f2
ldd [$key + 208], %f16
ldd [$key + 216], %f18
aes_dround01 %f20, %f4, %f2, %f0
aes_dround23 %f22, %f4, %f2, %f2
ldd [$key + 224], %f20
ldd [$key + 232], %f22
___
for ($i=1; $i<6; $i++) {
$code.=<<___;
aes_dround01 %f`16+8*$i+0`, %f0, %f2, %f4
aes_dround23 %f`16+8*$i+2`, %f0, %f2, %f2
aes_dround01 %f`16+8*$i+4`, %f4, %f2, %f0
aes_dround23 %f`16+8*$i+6`, %f4, %f2, %f2
___
}
$code.=<<___;
aes_dround01 %f16, %f0, %f2, %f4
aes_dround23 %f18, %f0, %f2, %f2
ldd [$key + 16], %f16
ldd [$key + 24], %f18
aes_dround01_l %f20, %f4, %f2, %f0
aes_dround23_l %f22, %f4, %f2, %f2
ldd [$key + 32], %f20
retl
ldd [$key + 40], %f22
.type _aes256_decrypt_1x,#function
.size _aes256_decrypt_1x,.-_aes256_decrypt_1x
.align 32
_aes256_decrypt_2x:
aes_dround01 %f16, %f0, %f2, %f8
aes_dround23 %f18, %f0, %f2, %f2
aes_dround01 %f16, %f4, %f6, %f10
aes_dround23 %f18, %f4, %f6, %f6
ldd [$key + 208], %f16
ldd [$key + 216], %f18
aes_dround01 %f20, %f8, %f2, %f0
aes_dround23 %f22, %f8, %f2, %f2
aes_dround01 %f20, %f10, %f6, %f4
aes_dround23 %f22, %f10, %f6, %f6
ldd [$key + 224], %f20
ldd [$key + 232], %f22
___
for ($i=1; $i<6; $i++) {
$code.=<<___;
aes_dround01 %f`16+8*$i+0`, %f0, %f2, %f8
aes_dround23 %f`16+8*$i+2`, %f0, %f2, %f2
aes_dround01 %f`16+8*$i+0`, %f4, %f6, %f10
aes_dround23 %f`16+8*$i+2`, %f4, %f6, %f6
aes_dround01 %f`16+8*$i+4`, %f8, %f2, %f0
aes_dround23 %f`16+8*$i+6`, %f8, %f2, %f2
aes_dround01 %f`16+8*$i+4`, %f10, %f6, %f4
aes_dround23 %f`16+8*$i+6`, %f10, %f6, %f6
___
}
$code.=<<___;
aes_dround01 %f16, %f0, %f2, %f8
aes_dround23 %f18, %f0, %f2, %f2
aes_dround01 %f16, %f4, %f6, %f10
aes_dround23 %f18, %f4, %f6, %f6
ldd [$key + 16], %f16
ldd [$key + 24], %f18
aes_dround01_l %f20, %f8, %f2, %f0
aes_dround23_l %f22, %f8, %f2, %f2
aes_dround01_l %f20, %f10, %f6, %f4
aes_dround23_l %f22, %f10, %f6, %f6
ldd [$key + 32], %f20
retl
ldd [$key + 40], %f22
.type _aes256_decrypt_2x,#function
.size _aes256_decrypt_2x,.-_aes256_decrypt_2x
.align 32
_aes192_decrypt_1x:
___
for ($i=0; $i<5; $i++) {
$code.=<<___;
aes_dround01 %f`16+8*$i+0`, %f0, %f2, %f4
aes_dround23 %f`16+8*$i+2`, %f0, %f2, %f2
aes_dround01 %f`16+8*$i+4`, %f4, %f2, %f0
aes_dround23 %f`16+8*$i+6`, %f4, %f2, %f2
___
}
$code.=<<___;
aes_dround01 %f56, %f0, %f2, %f4
aes_dround23 %f58, %f0, %f2, %f2
aes_dround01_l %f60, %f4, %f2, %f0
retl
aes_dround23_l %f62, %f4, %f2, %f2
.type _aes192_decrypt_1x,#function
.size _aes192_decrypt_1x,.-_aes192_decrypt_1x
.align 32
_aes192_decrypt_2x:
___
for ($i=0; $i<5; $i++) {
$code.=<<___;
aes_dround01 %f`16+8*$i+0`, %f0, %f2, %f8
aes_dround23 %f`16+8*$i+2`, %f0, %f2, %f2
aes_dround01 %f`16+8*$i+0`, %f4, %f6, %f10
aes_dround23 %f`16+8*$i+2`, %f4, %f6, %f6
aes_dround01 %f`16+8*$i+4`, %f8, %f2, %f0
aes_dround23 %f`16+8*$i+6`, %f8, %f2, %f2
aes_dround01 %f`16+8*$i+4`, %f10, %f6, %f4
aes_dround23 %f`16+8*$i+6`, %f10, %f6, %f6
___
}
$code.=<<___;
aes_dround01 %f56, %f0, %f2, %f8
aes_dround23 %f58, %f0, %f2, %f2
aes_dround01 %f56, %f4, %f6, %f10
aes_dround23 %f58, %f4, %f6, %f6
aes_dround01_l %f60, %f8, %f2, %f0
aes_dround23_l %f62, %f8, %f2, %f2
aes_dround01_l %f60, %f10, %f6, %f4
retl
aes_dround23_l %f62, %f10, %f6, %f6
.type _aes192_decrypt_2x,#function
.size _aes192_decrypt_2x,.-_aes192_decrypt_2x
___
}}}
if (!$::evp) {
$code.=<<___;
.global AES_encrypt
AES_encrypt=aes_t4_encrypt
.global AES_decrypt
AES_decrypt=aes_t4_decrypt
.global AES_set_encrypt_key
.align 32
AES_set_encrypt_key:
andcc %o2, 7, %g0 ! check alignment
bnz,a,pn %icc, 1f
mov -1, %o0
brz,a,pn %o0, 1f
mov -1, %o0
brz,a,pn %o2, 1f
mov -1, %o0
andncc %o1, 0x1c0, %g0
bnz,a,pn %icc, 1f
mov -2, %o0
cmp %o1, 128
bl,a,pn %icc, 1f
mov -2, %o0
b aes_t4_set_encrypt_key
nop
1: retl
nop
.type AES_set_encrypt_key,#function
.size AES_set_encrypt_key,.-AES_set_encrypt_key
.global AES_set_decrypt_key
.align 32
AES_set_decrypt_key:
andcc %o2, 7, %g0 ! check alignment
bnz,a,pn %icc, 1f
mov -1, %o0
brz,a,pn %o0, 1f
mov -1, %o0
brz,a,pn %o2, 1f
mov -1, %o0
andncc %o1, 0x1c0, %g0
bnz,a,pn %icc, 1f
mov -2, %o0
cmp %o1, 128
bl,a,pn %icc, 1f
mov -2, %o0
b aes_t4_set_decrypt_key
nop
1: retl
nop
.type AES_set_decrypt_key,#function
.size AES_set_decrypt_key,.-AES_set_decrypt_key
___
my ($inp,$out,$len,$key,$ivec,$enc)=map("%o$_",(0..5));
$code.=<<___;
.globl AES_cbc_encrypt
.align 32
AES_cbc_encrypt:
ld [$key + 240], %g1
nop
brz $enc, .Lcbc_decrypt
cmp %g1, 12
bl,pt %icc, aes128_t4_cbc_encrypt
nop
be,pn %icc, aes192_t4_cbc_encrypt
nop
ba aes256_t4_cbc_encrypt
nop
.Lcbc_decrypt:
bl,pt %icc, aes128_t4_cbc_decrypt
nop
be,pn %icc, aes192_t4_cbc_decrypt
nop
ba aes256_t4_cbc_decrypt
nop
.type AES_cbc_encrypt,#function
.size AES_cbc_encrypt,.-AES_cbc_encrypt
___
}
$code.=<<___;
.asciz "AES for SPARC T4, David S. Miller, Andy Polyakov"
.align 4
___
&emit_assembler();
close STDOUT;

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

View file

@ -0,0 +1,916 @@
#! /usr/bin/env perl
# Copyright 2011-2016 The OpenSSL Project Authors. All Rights Reserved.
#
# Licensed under the OpenSSL license (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
######################################################################
## Constant-time SSSE3 AES core implementation.
## version 0.1
##
## By Mike Hamburg (Stanford University), 2009
## Public domain.
##
## For details see http://shiftleft.org/papers/vector_aes/ and
## http://crypto.stanford.edu/vpaes/.
######################################################################
# September 2011.
#
# Port vpaes-x86_64.pl as 32-bit "almost" drop-in replacement for
# aes-586.pl. "Almost" refers to the fact that AES_cbc_encrypt
# doesn't handle partial vectors (doesn't have to if called from
# EVP only). "Drop-in" implies that this module doesn't share key
# schedule structure with the original nor does it make assumption
# about its alignment...
#
# Performance summary. aes-586.pl column lists large-block CBC
# encrypt/decrypt/with-hyper-threading-off(*) results in cycles per
# byte processed with 128-bit key, and vpaes-x86.pl column - [also
# large-block CBC] encrypt/decrypt.
#
# aes-586.pl vpaes-x86.pl
#
# Core 2(**) 28.1/41.4/18.3 21.9/25.2(***)
# Nehalem 27.9/40.4/18.1 10.2/11.9
# Atom 70.7/92.1/60.1 61.1/75.4(***)
# Silvermont 45.4/62.9/24.1 49.2/61.1(***)
#
# (*) "Hyper-threading" in the context refers rather to cache shared
# among multiple cores, than to specifically Intel HTT. As vast
# majority of contemporary cores share cache, slower code path
# is common place. In other words "with-hyper-threading-off"
# results are presented mostly for reference purposes.
#
# (**) "Core 2" refers to initial 65nm design, a.k.a. Conroe.
#
# (***) Less impressive improvement on Core 2 and Atom is due to slow
# pshufb, yet it's respectable +28%/64% improvement on Core 2
# and +15% on Atom (as implied, over "hyper-threading-safe"
# code path).
#
# <appro@openssl.org>
$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
push(@INC,"${dir}","${dir}../../perlasm");
require "x86asm.pl";
$output = pop;
open OUT,">$output";
*STDOUT=*OUT;
&asm_init($ARGV[0],$x86only = $ARGV[$#ARGV] eq "386");
$PREFIX="vpaes";
my ($round, $base, $magic, $key, $const, $inp, $out)=
("eax", "ebx", "ecx", "edx","ebp", "esi","edi");
&static_label("_vpaes_consts");
&static_label("_vpaes_schedule_low_round");
&set_label("_vpaes_consts",64);
$k_inv=-0x30; # inv, inva
&data_word(0x0D080180,0x0E05060F,0x0A0B0C02,0x04070309);
&data_word(0x0F0B0780,0x01040A06,0x02050809,0x030D0E0C);
$k_s0F=-0x10; # s0F
&data_word(0x0F0F0F0F,0x0F0F0F0F,0x0F0F0F0F,0x0F0F0F0F);
$k_ipt=0x00; # input transform (lo, hi)
&data_word(0x5A2A7000,0xC2B2E898,0x52227808,0xCABAE090);
&data_word(0x317C4D00,0x4C01307D,0xB0FDCC81,0xCD80B1FC);
$k_sb1=0x20; # sb1u, sb1t
&data_word(0xCB503E00,0xB19BE18F,0x142AF544,0xA5DF7A6E);
&data_word(0xFAE22300,0x3618D415,0x0D2ED9EF,0x3BF7CCC1);
$k_sb2=0x40; # sb2u, sb2t
&data_word(0x0B712400,0xE27A93C6,0xBC982FCD,0x5EB7E955);
&data_word(0x0AE12900,0x69EB8840,0xAB82234A,0xC2A163C8);
$k_sbo=0x60; # sbou, sbot
&data_word(0x6FBDC700,0xD0D26D17,0xC502A878,0x15AABF7A);
&data_word(0x5FBB6A00,0xCFE474A5,0x412B35FA,0x8E1E90D1);
$k_mc_forward=0x80; # mc_forward
&data_word(0x00030201,0x04070605,0x080B0A09,0x0C0F0E0D);
&data_word(0x04070605,0x080B0A09,0x0C0F0E0D,0x00030201);
&data_word(0x080B0A09,0x0C0F0E0D,0x00030201,0x04070605);
&data_word(0x0C0F0E0D,0x00030201,0x04070605,0x080B0A09);
$k_mc_backward=0xc0; # mc_backward
&data_word(0x02010003,0x06050407,0x0A09080B,0x0E0D0C0F);
&data_word(0x0E0D0C0F,0x02010003,0x06050407,0x0A09080B);
&data_word(0x0A09080B,0x0E0D0C0F,0x02010003,0x06050407);
&data_word(0x06050407,0x0A09080B,0x0E0D0C0F,0x02010003);
$k_sr=0x100; # sr
&data_word(0x03020100,0x07060504,0x0B0A0908,0x0F0E0D0C);
&data_word(0x0F0A0500,0x030E0904,0x07020D08,0x0B06010C);
&data_word(0x0B020900,0x0F060D04,0x030A0108,0x070E050C);
&data_word(0x070A0D00,0x0B0E0104,0x0F020508,0x0306090C);
$k_rcon=0x140; # rcon
&data_word(0xAF9DEEB6,0x1F8391B9,0x4D7C7D81,0x702A9808);
$k_s63=0x150; # s63: all equal to 0x63 transformed
&data_word(0x5B5B5B5B,0x5B5B5B5B,0x5B5B5B5B,0x5B5B5B5B);
$k_opt=0x160; # output transform
&data_word(0xD6B66000,0xFF9F4929,0xDEBE6808,0xF7974121);
&data_word(0x50BCEC00,0x01EDBD51,0xB05C0CE0,0xE10D5DB1);
$k_deskew=0x180; # deskew tables: inverts the sbox's "skew"
&data_word(0x47A4E300,0x07E4A340,0x5DBEF91A,0x1DFEB95A);
&data_word(0x83EA6900,0x5F36B5DC,0xF49D1E77,0x2841C2AB);
##
## Decryption stuff
## Key schedule constants
##
$k_dksd=0x1a0; # decryption key schedule: invskew x*D
&data_word(0xA3E44700,0xFEB91A5D,0x5A1DBEF9,0x0740E3A4);
&data_word(0xB5368300,0x41C277F4,0xAB289D1E,0x5FDC69EA);
$k_dksb=0x1c0; # decryption key schedule: invskew x*B
&data_word(0x8550D500,0x9A4FCA1F,0x1CC94C99,0x03D65386);
&data_word(0xB6FC4A00,0x115BEDA7,0x7E3482C8,0xD993256F);
$k_dkse=0x1e0; # decryption key schedule: invskew x*E + 0x63
&data_word(0x1FC9D600,0xD5031CCA,0x994F5086,0x53859A4C);
&data_word(0x4FDC7BE8,0xA2319605,0x20B31487,0xCD5EF96A);
$k_dks9=0x200; # decryption key schedule: invskew x*9
&data_word(0x7ED9A700,0xB6116FC8,0x82255BFC,0x4AED9334);
&data_word(0x27143300,0x45765162,0xE9DAFDCE,0x8BB89FAC);
##
## Decryption stuff
## Round function constants
##
$k_dipt=0x220; # decryption input transform
&data_word(0x0B545F00,0x0F505B04,0x114E451A,0x154A411E);
&data_word(0x60056500,0x86E383E6,0xF491F194,0x12771772);
$k_dsb9=0x240; # decryption sbox output *9*u, *9*t
&data_word(0x9A86D600,0x851C0353,0x4F994CC9,0xCAD51F50);
&data_word(0xECD74900,0xC03B1789,0xB2FBA565,0x725E2C9E);
$k_dsbd=0x260; # decryption sbox output *D*u, *D*t
&data_word(0xE6B1A200,0x7D57CCDF,0x882A4439,0xF56E9B13);
&data_word(0x24C6CB00,0x3CE2FAF7,0x15DEEFD3,0x2931180D);
$k_dsbb=0x280; # decryption sbox output *B*u, *B*t
&data_word(0x96B44200,0xD0226492,0xB0F2D404,0x602646F6);
&data_word(0xCD596700,0xC19498A6,0x3255AA6B,0xF3FF0C3E);
$k_dsbe=0x2a0; # decryption sbox output *E*u, *E*t
&data_word(0x26D4D000,0x46F29296,0x64B4F6B0,0x22426004);
&data_word(0xFFAAC100,0x0C55A6CD,0x98593E32,0x9467F36B);
$k_dsbo=0x2c0; # decryption sbox final output
&data_word(0x7EF94000,0x1387EA53,0xD4943E2D,0xC7AA6DB9);
&data_word(0x93441D00,0x12D7560F,0xD8C58E9C,0xCA4B8159);
&asciz ("Vector Permutation AES for x86/SSSE3, Mike Hamburg (Stanford University)");
&align (64);
&function_begin_B("_vpaes_preheat");
&add ($const,&DWP(0,"esp"));
&movdqa ("xmm7",&QWP($k_inv,$const));
&movdqa ("xmm6",&QWP($k_s0F,$const));
&ret ();
&function_end_B("_vpaes_preheat");
##
## _aes_encrypt_core
##
## AES-encrypt %xmm0.
##
## Inputs:
## %xmm0 = input
## %xmm6-%xmm7 as in _vpaes_preheat
## (%edx) = scheduled keys
##
## Output in %xmm0
## Clobbers %xmm1-%xmm5, %eax, %ebx, %ecx, %edx
##
##
&function_begin_B("_vpaes_encrypt_core");
&mov ($magic,16);
&mov ($round,&DWP(240,$key));
&movdqa ("xmm1","xmm6")
&movdqa ("xmm2",&QWP($k_ipt,$const));
&pandn ("xmm1","xmm0");
&pand ("xmm0","xmm6");
&movdqu ("xmm5",&QWP(0,$key));
&pshufb ("xmm2","xmm0");
&movdqa ("xmm0",&QWP($k_ipt+16,$const));
&pxor ("xmm2","xmm5");
&psrld ("xmm1",4);
&add ($key,16);
&pshufb ("xmm0","xmm1");
&lea ($base,&DWP($k_mc_backward,$const));
&pxor ("xmm0","xmm2");
&jmp (&label("enc_entry"));
&set_label("enc_loop",16);
# middle of middle round
&movdqa ("xmm4",&QWP($k_sb1,$const)); # 4 : sb1u
&movdqa ("xmm0",&QWP($k_sb1+16,$const));# 0 : sb1t
&pshufb ("xmm4","xmm2"); # 4 = sb1u
&pshufb ("xmm0","xmm3"); # 0 = sb1t
&pxor ("xmm4","xmm5"); # 4 = sb1u + k
&movdqa ("xmm5",&QWP($k_sb2,$const)); # 4 : sb2u
&pxor ("xmm0","xmm4"); # 0 = A
&movdqa ("xmm1",&QWP(-0x40,$base,$magic));# .Lk_mc_forward[]
&pshufb ("xmm5","xmm2"); # 4 = sb2u
&movdqa ("xmm2",&QWP($k_sb2+16,$const));# 2 : sb2t
&movdqa ("xmm4",&QWP(0,$base,$magic)); # .Lk_mc_backward[]
&pshufb ("xmm2","xmm3"); # 2 = sb2t
&movdqa ("xmm3","xmm0"); # 3 = A
&pxor ("xmm2","xmm5"); # 2 = 2A
&pshufb ("xmm0","xmm1"); # 0 = B
&add ($key,16); # next key
&pxor ("xmm0","xmm2"); # 0 = 2A+B
&pshufb ("xmm3","xmm4"); # 3 = D
&add ($magic,16); # next mc
&pxor ("xmm3","xmm0"); # 3 = 2A+B+D
&pshufb ("xmm0","xmm1"); # 0 = 2B+C
&and ($magic,0x30); # ... mod 4
&sub ($round,1); # nr--
&pxor ("xmm0","xmm3"); # 0 = 2A+3B+C+D
&set_label("enc_entry");
# top of round
&movdqa ("xmm1","xmm6"); # 1 : i
&movdqa ("xmm5",&QWP($k_inv+16,$const));# 2 : a/k
&pandn ("xmm1","xmm0"); # 1 = i<<4
&psrld ("xmm1",4); # 1 = i
&pand ("xmm0","xmm6"); # 0 = k
&pshufb ("xmm5","xmm0"); # 2 = a/k
&movdqa ("xmm3","xmm7"); # 3 : 1/i
&pxor ("xmm0","xmm1"); # 0 = j
&pshufb ("xmm3","xmm1"); # 3 = 1/i
&movdqa ("xmm4","xmm7"); # 4 : 1/j
&pxor ("xmm3","xmm5"); # 3 = iak = 1/i + a/k
&pshufb ("xmm4","xmm0"); # 4 = 1/j
&movdqa ("xmm2","xmm7"); # 2 : 1/iak
&pxor ("xmm4","xmm5"); # 4 = jak = 1/j + a/k
&pshufb ("xmm2","xmm3"); # 2 = 1/iak
&movdqa ("xmm3","xmm7"); # 3 : 1/jak
&pxor ("xmm2","xmm0"); # 2 = io
&pshufb ("xmm3","xmm4"); # 3 = 1/jak
&movdqu ("xmm5",&QWP(0,$key));
&pxor ("xmm3","xmm1"); # 3 = jo
&jnz (&label("enc_loop"));
# middle of last round
&movdqa ("xmm4",&QWP($k_sbo,$const)); # 3 : sbou .Lk_sbo
&movdqa ("xmm0",&QWP($k_sbo+16,$const));# 3 : sbot .Lk_sbo+16
&pshufb ("xmm4","xmm2"); # 4 = sbou
&pxor ("xmm4","xmm5"); # 4 = sb1u + k
&pshufb ("xmm0","xmm3"); # 0 = sb1t
&movdqa ("xmm1",&QWP(0x40,$base,$magic));# .Lk_sr[]
&pxor ("xmm0","xmm4"); # 0 = A
&pshufb ("xmm0","xmm1");
&ret ();
&function_end_B("_vpaes_encrypt_core");
##
## Decryption core
##
## Same API as encryption core.
##
&function_begin_B("_vpaes_decrypt_core");
&lea ($base,&DWP($k_dsbd,$const));
&mov ($round,&DWP(240,$key));
&movdqa ("xmm1","xmm6");
&movdqa ("xmm2",&QWP($k_dipt-$k_dsbd,$base));
&pandn ("xmm1","xmm0");
&mov ($magic,$round);
&psrld ("xmm1",4)
&movdqu ("xmm5",&QWP(0,$key));
&shl ($magic,4);
&pand ("xmm0","xmm6");
&pshufb ("xmm2","xmm0");
&movdqa ("xmm0",&QWP($k_dipt-$k_dsbd+16,$base));
&xor ($magic,0x30);
&pshufb ("xmm0","xmm1");
&and ($magic,0x30);
&pxor ("xmm2","xmm5");
&movdqa ("xmm5",&QWP($k_mc_forward+48,$const));
&pxor ("xmm0","xmm2");
&add ($key,16);
&lea ($magic,&DWP($k_sr-$k_dsbd,$base,$magic));
&jmp (&label("dec_entry"));
&set_label("dec_loop",16);
##
## Inverse mix columns
##
&movdqa ("xmm4",&QWP(-0x20,$base)); # 4 : sb9u
&movdqa ("xmm1",&QWP(-0x10,$base)); # 0 : sb9t
&pshufb ("xmm4","xmm2"); # 4 = sb9u
&pshufb ("xmm1","xmm3"); # 0 = sb9t
&pxor ("xmm0","xmm4");
&movdqa ("xmm4",&QWP(0,$base)); # 4 : sbdu
&pxor ("xmm0","xmm1"); # 0 = ch
&movdqa ("xmm1",&QWP(0x10,$base)); # 0 : sbdt
&pshufb ("xmm4","xmm2"); # 4 = sbdu
&pshufb ("xmm0","xmm5"); # MC ch
&pshufb ("xmm1","xmm3"); # 0 = sbdt
&pxor ("xmm0","xmm4"); # 4 = ch
&movdqa ("xmm4",&QWP(0x20,$base)); # 4 : sbbu
&pxor ("xmm0","xmm1"); # 0 = ch
&movdqa ("xmm1",&QWP(0x30,$base)); # 0 : sbbt
&pshufb ("xmm4","xmm2"); # 4 = sbbu
&pshufb ("xmm0","xmm5"); # MC ch
&pshufb ("xmm1","xmm3"); # 0 = sbbt
&pxor ("xmm0","xmm4"); # 4 = ch
&movdqa ("xmm4",&QWP(0x40,$base)); # 4 : sbeu
&pxor ("xmm0","xmm1"); # 0 = ch
&movdqa ("xmm1",&QWP(0x50,$base)); # 0 : sbet
&pshufb ("xmm4","xmm2"); # 4 = sbeu
&pshufb ("xmm0","xmm5"); # MC ch
&pshufb ("xmm1","xmm3"); # 0 = sbet
&pxor ("xmm0","xmm4"); # 4 = ch
&add ($key,16); # next round key
&palignr("xmm5","xmm5",12);
&pxor ("xmm0","xmm1"); # 0 = ch
&sub ($round,1); # nr--
&set_label("dec_entry");
# top of round
&movdqa ("xmm1","xmm6"); # 1 : i
&movdqa ("xmm2",&QWP($k_inv+16,$const));# 2 : a/k
&pandn ("xmm1","xmm0"); # 1 = i<<4
&pand ("xmm0","xmm6"); # 0 = k
&psrld ("xmm1",4); # 1 = i
&pshufb ("xmm2","xmm0"); # 2 = a/k
&movdqa ("xmm3","xmm7"); # 3 : 1/i
&pxor ("xmm0","xmm1"); # 0 = j
&pshufb ("xmm3","xmm1"); # 3 = 1/i
&movdqa ("xmm4","xmm7"); # 4 : 1/j
&pxor ("xmm3","xmm2"); # 3 = iak = 1/i + a/k
&pshufb ("xmm4","xmm0"); # 4 = 1/j
&pxor ("xmm4","xmm2"); # 4 = jak = 1/j + a/k
&movdqa ("xmm2","xmm7"); # 2 : 1/iak
&pshufb ("xmm2","xmm3"); # 2 = 1/iak
&movdqa ("xmm3","xmm7"); # 3 : 1/jak
&pxor ("xmm2","xmm0"); # 2 = io
&pshufb ("xmm3","xmm4"); # 3 = 1/jak
&movdqu ("xmm0",&QWP(0,$key));
&pxor ("xmm3","xmm1"); # 3 = jo
&jnz (&label("dec_loop"));
# middle of last round
&movdqa ("xmm4",&QWP(0x60,$base)); # 3 : sbou
&pshufb ("xmm4","xmm2"); # 4 = sbou
&pxor ("xmm4","xmm0"); # 4 = sb1u + k
&movdqa ("xmm0",&QWP(0x70,$base)); # 0 : sbot
&movdqa ("xmm2",&QWP(0,$magic));
&pshufb ("xmm0","xmm3"); # 0 = sb1t
&pxor ("xmm0","xmm4"); # 0 = A
&pshufb ("xmm0","xmm2");
&ret ();
&function_end_B("_vpaes_decrypt_core");
########################################################
## ##
## AES key schedule ##
## ##
########################################################
&function_begin_B("_vpaes_schedule_core");
&add ($const,&DWP(0,"esp"));
&movdqu ("xmm0",&QWP(0,$inp)); # load key (unaligned)
&movdqa ("xmm2",&QWP($k_rcon,$const)); # load rcon
# input transform
&movdqa ("xmm3","xmm0");
&lea ($base,&DWP($k_ipt,$const));
&movdqa (&QWP(4,"esp"),"xmm2"); # xmm8
&call ("_vpaes_schedule_transform");
&movdqa ("xmm7","xmm0");
&test ($out,$out);
&jnz (&label("schedule_am_decrypting"));
# encrypting, output zeroth round key after transform
&movdqu (&QWP(0,$key),"xmm0");
&jmp (&label("schedule_go"));
&set_label("schedule_am_decrypting");
# decrypting, output zeroth round key after shiftrows
&movdqa ("xmm1",&QWP($k_sr,$const,$magic));
&pshufb ("xmm3","xmm1");
&movdqu (&QWP(0,$key),"xmm3");
&xor ($magic,0x30);
&set_label("schedule_go");
&cmp ($round,192);
&ja (&label("schedule_256"));
&je (&label("schedule_192"));
# 128: fall though
##
## .schedule_128
##
## 128-bit specific part of key schedule.
##
## This schedule is really simple, because all its parts
## are accomplished by the subroutines.
##
&set_label("schedule_128");
&mov ($round,10);
&set_label("loop_schedule_128");
&call ("_vpaes_schedule_round");
&dec ($round);
&jz (&label("schedule_mangle_last"));
&call ("_vpaes_schedule_mangle"); # write output
&jmp (&label("loop_schedule_128"));
##
## .aes_schedule_192
##
## 192-bit specific part of key schedule.
##
## The main body of this schedule is the same as the 128-bit
## schedule, but with more smearing. The long, high side is
## stored in %xmm7 as before, and the short, low side is in
## the high bits of %xmm6.
##
## This schedule is somewhat nastier, however, because each
## round produces 192 bits of key material, or 1.5 round keys.
## Therefore, on each cycle we do 2 rounds and produce 3 round
## keys.
##
&set_label("schedule_192",16);
&movdqu ("xmm0",&QWP(8,$inp)); # load key part 2 (very unaligned)
&call ("_vpaes_schedule_transform"); # input transform
&movdqa ("xmm6","xmm0"); # save short part
&pxor ("xmm4","xmm4"); # clear 4
&movhlps("xmm6","xmm4"); # clobber low side with zeros
&mov ($round,4);
&set_label("loop_schedule_192");
&call ("_vpaes_schedule_round");
&palignr("xmm0","xmm6",8);
&call ("_vpaes_schedule_mangle"); # save key n
&call ("_vpaes_schedule_192_smear");
&call ("_vpaes_schedule_mangle"); # save key n+1
&call ("_vpaes_schedule_round");
&dec ($round);
&jz (&label("schedule_mangle_last"));
&call ("_vpaes_schedule_mangle"); # save key n+2
&call ("_vpaes_schedule_192_smear");
&jmp (&label("loop_schedule_192"));
##
## .aes_schedule_256
##
## 256-bit specific part of key schedule.
##
## The structure here is very similar to the 128-bit
## schedule, but with an additional "low side" in
## %xmm6. The low side's rounds are the same as the
## high side's, except no rcon and no rotation.
##
&set_label("schedule_256",16);
&movdqu ("xmm0",&QWP(16,$inp)); # load key part 2 (unaligned)
&call ("_vpaes_schedule_transform"); # input transform
&mov ($round,7);
&set_label("loop_schedule_256");
&call ("_vpaes_schedule_mangle"); # output low result
&movdqa ("xmm6","xmm0"); # save cur_lo in xmm6
# high round
&call ("_vpaes_schedule_round");
&dec ($round);
&jz (&label("schedule_mangle_last"));
&call ("_vpaes_schedule_mangle");
# low round. swap xmm7 and xmm6
&pshufd ("xmm0","xmm0",0xFF);
&movdqa (&QWP(20,"esp"),"xmm7");
&movdqa ("xmm7","xmm6");
&call ("_vpaes_schedule_low_round");
&movdqa ("xmm7",&QWP(20,"esp"));
&jmp (&label("loop_schedule_256"));
##
## .aes_schedule_mangle_last
##
## Mangler for last round of key schedule
## Mangles %xmm0
## when encrypting, outputs out(%xmm0) ^ 63
## when decrypting, outputs unskew(%xmm0)
##
## Always called right before return... jumps to cleanup and exits
##
&set_label("schedule_mangle_last",16);
# schedule last round key from xmm0
&lea ($base,&DWP($k_deskew,$const));
&test ($out,$out);
&jnz (&label("schedule_mangle_last_dec"));
# encrypting
&movdqa ("xmm1",&QWP($k_sr,$const,$magic));
&pshufb ("xmm0","xmm1"); # output permute
&lea ($base,&DWP($k_opt,$const)); # prepare to output transform
&add ($key,32);
&set_label("schedule_mangle_last_dec");
&add ($key,-16);
&pxor ("xmm0",&QWP($k_s63,$const));
&call ("_vpaes_schedule_transform"); # output transform
&movdqu (&QWP(0,$key),"xmm0"); # save last key
# cleanup
&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 ();
&function_end_B("_vpaes_schedule_core");
##
## .aes_schedule_192_smear
##
## Smear the short, low side in the 192-bit key schedule.
##
## Inputs:
## %xmm7: high side, b a x y
## %xmm6: low side, d c 0 0
## %xmm13: 0
##
## Outputs:
## %xmm6: b+c+d b+c 0 0
## %xmm0: b+c+d b+c b a
##
&function_begin_B("_vpaes_schedule_192_smear");
&pshufd ("xmm1","xmm6",0x80); # d c 0 0 -> c 0 0 0
&pshufd ("xmm0","xmm7",0xFE); # b a _ _ -> b b b a
&pxor ("xmm6","xmm1"); # -> c+d c 0 0
&pxor ("xmm1","xmm1");
&pxor ("xmm6","xmm0"); # -> b+c+d b+c b a
&movdqa ("xmm0","xmm6");
&movhlps("xmm6","xmm1"); # clobber low side with zeros
&ret ();
&function_end_B("_vpaes_schedule_192_smear");
##
## .aes_schedule_round
##
## Runs one main round of the key schedule on %xmm0, %xmm7
##
## Specifically, runs subbytes on the high dword of %xmm0
## then rotates it by one byte and xors into the low dword of
## %xmm7.
##
## Adds rcon from low byte of %xmm8, then rotates %xmm8 for
## next rcon.
##
## Smears the dwords of %xmm7 by xoring the low into the
## second low, result into third, result into highest.
##
## Returns results in %xmm7 = %xmm0.
## Clobbers %xmm1-%xmm5.
##
&function_begin_B("_vpaes_schedule_round");
# extract rcon from xmm8
&movdqa ("xmm2",&QWP(8,"esp")); # xmm8
&pxor ("xmm1","xmm1");
&palignr("xmm1","xmm2",15);
&palignr("xmm2","xmm2",15);
&pxor ("xmm7","xmm1");
# rotate
&pshufd ("xmm0","xmm0",0xFF);
&palignr("xmm0","xmm0",1);
# fall through...
&movdqa (&QWP(8,"esp"),"xmm2"); # xmm8
# low round: same as high round, but no rotation and no rcon.
&set_label("_vpaes_schedule_low_round");
# smear xmm7
&movdqa ("xmm1","xmm7");
&pslldq ("xmm7",4);
&pxor ("xmm7","xmm1");
&movdqa ("xmm1","xmm7");
&pslldq ("xmm7",8);
&pxor ("xmm7","xmm1");
&pxor ("xmm7",&QWP($k_s63,$const));
# subbyte
&movdqa ("xmm4",&QWP($k_s0F,$const));
&movdqa ("xmm5",&QWP($k_inv,$const)); # 4 : 1/j
&movdqa ("xmm1","xmm4");
&pandn ("xmm1","xmm0");
&psrld ("xmm1",4); # 1 = i
&pand ("xmm0","xmm4"); # 0 = k
&movdqa ("xmm2",&QWP($k_inv+16,$const));# 2 : a/k
&pshufb ("xmm2","xmm0"); # 2 = a/k
&pxor ("xmm0","xmm1"); # 0 = j
&movdqa ("xmm3","xmm5"); # 3 : 1/i
&pshufb ("xmm3","xmm1"); # 3 = 1/i
&pxor ("xmm3","xmm2"); # 3 = iak = 1/i + a/k
&movdqa ("xmm4","xmm5"); # 4 : 1/j
&pshufb ("xmm4","xmm0"); # 4 = 1/j
&pxor ("xmm4","xmm2"); # 4 = jak = 1/j + a/k
&movdqa ("xmm2","xmm5"); # 2 : 1/iak
&pshufb ("xmm2","xmm3"); # 2 = 1/iak
&pxor ("xmm2","xmm0"); # 2 = io
&movdqa ("xmm3","xmm5"); # 3 : 1/jak
&pshufb ("xmm3","xmm4"); # 3 = 1/jak
&pxor ("xmm3","xmm1"); # 3 = jo
&movdqa ("xmm4",&QWP($k_sb1,$const)); # 4 : sbou
&pshufb ("xmm4","xmm2"); # 4 = sbou
&movdqa ("xmm0",&QWP($k_sb1+16,$const));# 0 : sbot
&pshufb ("xmm0","xmm3"); # 0 = sb1t
&pxor ("xmm0","xmm4"); # 0 = sbox output
# add in smeared stuff
&pxor ("xmm0","xmm7");
&movdqa ("xmm7","xmm0");
&ret ();
&function_end_B("_vpaes_schedule_round");
##
## .aes_schedule_transform
##
## Linear-transform %xmm0 according to tables at (%ebx)
##
## Output in %xmm0
## Clobbers %xmm1, %xmm2
##
&function_begin_B("_vpaes_schedule_transform");
&movdqa ("xmm2",&QWP($k_s0F,$const));
&movdqa ("xmm1","xmm2");
&pandn ("xmm1","xmm0");
&psrld ("xmm1",4);
&pand ("xmm0","xmm2");
&movdqa ("xmm2",&QWP(0,$base));
&pshufb ("xmm2","xmm0");
&movdqa ("xmm0",&QWP(16,$base));
&pshufb ("xmm0","xmm1");
&pxor ("xmm0","xmm2");
&ret ();
&function_end_B("_vpaes_schedule_transform");
##
## .aes_schedule_mangle
##
## Mangle xmm0 from (basis-transformed) standard version
## to our version.
##
## On encrypt,
## xor with 0x63
## multiply by circulant 0,1,1,1
## apply shiftrows transform
##
## On decrypt,
## xor with 0x63
## multiply by "inverse mixcolumns" circulant E,B,D,9
## deskew
## apply shiftrows transform
##
##
## Writes out to (%edx), and increments or decrements it
## Keeps track of round number mod 4 in %ecx
## Preserves xmm0
## Clobbers xmm1-xmm5
##
&function_begin_B("_vpaes_schedule_mangle");
&movdqa ("xmm4","xmm0"); # save xmm0 for later
&movdqa ("xmm5",&QWP($k_mc_forward,$const));
&test ($out,$out);
&jnz (&label("schedule_mangle_dec"));
# encrypting
&add ($key,16);
&pxor ("xmm4",&QWP($k_s63,$const));
&pshufb ("xmm4","xmm5");
&movdqa ("xmm3","xmm4");
&pshufb ("xmm4","xmm5");
&pxor ("xmm3","xmm4");
&pshufb ("xmm4","xmm5");
&pxor ("xmm3","xmm4");
&jmp (&label("schedule_mangle_both"));
&set_label("schedule_mangle_dec",16);
# inverse mix columns
&movdqa ("xmm2",&QWP($k_s0F,$const));
&lea ($inp,&DWP($k_dksd,$const));
&movdqa ("xmm1","xmm2");
&pandn ("xmm1","xmm4");
&psrld ("xmm1",4); # 1 = hi
&pand ("xmm4","xmm2"); # 4 = lo
&movdqa ("xmm2",&QWP(0,$inp));
&pshufb ("xmm2","xmm4");
&movdqa ("xmm3",&QWP(0x10,$inp));
&pshufb ("xmm3","xmm1");
&pxor ("xmm3","xmm2");
&pshufb ("xmm3","xmm5");
&movdqa ("xmm2",&QWP(0x20,$inp));
&pshufb ("xmm2","xmm4");
&pxor ("xmm2","xmm3");
&movdqa ("xmm3",&QWP(0x30,$inp));
&pshufb ("xmm3","xmm1");
&pxor ("xmm3","xmm2");
&pshufb ("xmm3","xmm5");
&movdqa ("xmm2",&QWP(0x40,$inp));
&pshufb ("xmm2","xmm4");
&pxor ("xmm2","xmm3");
&movdqa ("xmm3",&QWP(0x50,$inp));
&pshufb ("xmm3","xmm1");
&pxor ("xmm3","xmm2");
&pshufb ("xmm3","xmm5");
&movdqa ("xmm2",&QWP(0x60,$inp));
&pshufb ("xmm2","xmm4");
&pxor ("xmm2","xmm3");
&movdqa ("xmm3",&QWP(0x70,$inp));
&pshufb ("xmm3","xmm1");
&pxor ("xmm3","xmm2");
&add ($key,-16);
&set_label("schedule_mangle_both");
&movdqa ("xmm1",&QWP($k_sr,$const,$magic));
&pshufb ("xmm3","xmm1");
&add ($magic,-16);
&and ($magic,0x30);
&movdqu (&QWP(0,$key),"xmm3");
&ret ();
&function_end_B("_vpaes_schedule_mangle");
#
# Interface to OpenSSL
#
&function_begin("${PREFIX}_set_encrypt_key");
&mov ($inp,&wparam(0)); # inp
&lea ($base,&DWP(-56,"esp"));
&mov ($round,&wparam(1)); # bits
&and ($base,-16);
&mov ($key,&wparam(2)); # key
&xchg ($base,"esp"); # alloca
&mov (&DWP(48,"esp"),$base);
&mov ($base,$round);
&shr ($base,5);
&add ($base,5);
&mov (&DWP(240,$key),$base); # AES_KEY->rounds = nbits/32+5;
&mov ($magic,0x30);
&mov ($out,0);
&lea ($const,&DWP(&label("_vpaes_consts")."+0x30-".&label("pic_point")));
&call ("_vpaes_schedule_core");
&set_label("pic_point");
&mov ("esp",&DWP(48,"esp"));
&xor ("eax","eax");
&function_end("${PREFIX}_set_encrypt_key");
&function_begin("${PREFIX}_set_decrypt_key");
&mov ($inp,&wparam(0)); # inp
&lea ($base,&DWP(-56,"esp"));
&mov ($round,&wparam(1)); # bits
&and ($base,-16);
&mov ($key,&wparam(2)); # key
&xchg ($base,"esp"); # alloca
&mov (&DWP(48,"esp"),$base);
&mov ($base,$round);
&shr ($base,5);
&add ($base,5);
&mov (&DWP(240,$key),$base); # AES_KEY->rounds = nbits/32+5;
&shl ($base,4);
&lea ($key,&DWP(16,$key,$base));
&mov ($out,1);
&mov ($magic,$round);
&shr ($magic,1);
&and ($magic,32);
&xor ($magic,32); # nbist==192?0:32;
&lea ($const,&DWP(&label("_vpaes_consts")."+0x30-".&label("pic_point")));
&call ("_vpaes_schedule_core");
&set_label("pic_point");
&mov ("esp",&DWP(48,"esp"));
&xor ("eax","eax");
&function_end("${PREFIX}_set_decrypt_key");
&function_begin("${PREFIX}_encrypt");
&lea ($const,&DWP(&label("_vpaes_consts")."+0x30-".&label("pic_point")));
&call ("_vpaes_preheat");
&set_label("pic_point");
&mov ($inp,&wparam(0)); # inp
&lea ($base,&DWP(-56,"esp"));
&mov ($out,&wparam(1)); # out
&and ($base,-16);
&mov ($key,&wparam(2)); # key
&xchg ($base,"esp"); # alloca
&mov (&DWP(48,"esp"),$base);
&movdqu ("xmm0",&QWP(0,$inp));
&call ("_vpaes_encrypt_core");
&movdqu (&QWP(0,$out),"xmm0");
&mov ("esp",&DWP(48,"esp"));
&function_end("${PREFIX}_encrypt");
&function_begin("${PREFIX}_decrypt");
&lea ($const,&DWP(&label("_vpaes_consts")."+0x30-".&label("pic_point")));
&call ("_vpaes_preheat");
&set_label("pic_point");
&mov ($inp,&wparam(0)); # inp
&lea ($base,&DWP(-56,"esp"));
&mov ($out,&wparam(1)); # out
&and ($base,-16);
&mov ($key,&wparam(2)); # key
&xchg ($base,"esp"); # alloca
&mov (&DWP(48,"esp"),$base);
&movdqu ("xmm0",&QWP(0,$inp));
&call ("_vpaes_decrypt_core");
&movdqu (&QWP(0,$out),"xmm0");
&mov ("esp",&DWP(48,"esp"));
&function_end("${PREFIX}_decrypt");
&function_begin("${PREFIX}_cbc_encrypt");
&mov ($inp,&wparam(0)); # inp
&mov ($out,&wparam(1)); # out
&mov ($round,&wparam(2)); # len
&mov ($key,&wparam(3)); # key
&sub ($round,16);
&jc (&label("cbc_abort"));
&lea ($base,&DWP(-56,"esp"));
&mov ($const,&wparam(4)); # ivp
&and ($base,-16);
&mov ($magic,&wparam(5)); # enc
&xchg ($base,"esp"); # alloca
&movdqu ("xmm1",&QWP(0,$const)); # load IV
&sub ($out,$inp);
&mov (&DWP(48,"esp"),$base);
&mov (&DWP(0,"esp"),$out); # save out
&mov (&DWP(4,"esp"),$key) # save key
&mov (&DWP(8,"esp"),$const); # save ivp
&mov ($out,$round); # $out works as $len
&lea ($const,&DWP(&label("_vpaes_consts")."+0x30-".&label("pic_point")));
&call ("_vpaes_preheat");
&set_label("pic_point");
&cmp ($magic,0);
&je (&label("cbc_dec_loop"));
&jmp (&label("cbc_enc_loop"));
&set_label("cbc_enc_loop",16);
&movdqu ("xmm0",&QWP(0,$inp)); # load input
&pxor ("xmm0","xmm1"); # inp^=iv
&call ("_vpaes_encrypt_core");
&mov ($base,&DWP(0,"esp")); # restore out
&mov ($key,&DWP(4,"esp")); # restore key
&movdqa ("xmm1","xmm0");
&movdqu (&QWP(0,$base,$inp),"xmm0"); # write output
&lea ($inp,&DWP(16,$inp));
&sub ($out,16);
&jnc (&label("cbc_enc_loop"));
&jmp (&label("cbc_done"));
&set_label("cbc_dec_loop",16);
&movdqu ("xmm0",&QWP(0,$inp)); # load input
&movdqa (&QWP(16,"esp"),"xmm1"); # save IV
&movdqa (&QWP(32,"esp"),"xmm0"); # save future IV
&call ("_vpaes_decrypt_core");
&mov ($base,&DWP(0,"esp")); # restore out
&mov ($key,&DWP(4,"esp")); # restore key
&pxor ("xmm0",&QWP(16,"esp")); # out^=iv
&movdqa ("xmm1",&QWP(32,"esp")); # load next IV
&movdqu (&QWP(0,$base,$inp),"xmm0"); # write output
&lea ($inp,&DWP(16,$inp));
&sub ($out,16);
&jnc (&label("cbc_dec_loop"));
&set_label("cbc_done");
&mov ($base,&DWP(8,"esp")); # restore ivp
&mov ("esp",&DWP(48,"esp"));
&movdqu (&QWP(0,$base),"xmm1"); # write IV
&set_label("cbc_abort");
&function_end("${PREFIX}_cbc_encrypt");
&asm_finish();
close STDOUT;

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,64 @@
LIBS=../../libcrypto
SOURCE[../../libcrypto]=\
aes_misc.c aes_ecb.c aes_cfb.c aes_ofb.c \
aes_ige.c aes_wrap.c {- $target{aes_asm_src} -}
GENERATE[aes-ia64.s]=asm/aes-ia64.S
GENERATE[aes-586.s]=asm/aes-586.pl \
$(PERLASM_SCHEME) $(LIB_CFLAGS) $(LIB_CPPFLAGS) $(PROCESSOR)
DEPEND[aes-586.s]=../perlasm/x86asm.pl
GENERATE[vpaes-x86.s]=asm/vpaes-x86.pl \
$(PERLASM_SCHEME) $(LIB_CFLAGS) $(LIB_CPPFLAGS) $(PROCESSOR)
DEPEND[vpaes-586.s]=../perlasm/x86asm.pl
GENERATE[aesni-x86.s]=asm/aesni-x86.pl \
$(PERLASM_SCHEME) $(LIB_CFLAGS) $(LIB_CPPFLAGS) $(PROCESSOR)
DEPEND[aesni-586.s]=../perlasm/x86asm.pl
GENERATE[aes-x86_64.s]=asm/aes-x86_64.pl $(PERLASM_SCHEME)
GENERATE[vpaes-x86_64.s]=asm/vpaes-x86_64.pl $(PERLASM_SCHEME)
GENERATE[bsaes-x86_64.s]=asm/bsaes-x86_64.pl $(PERLASM_SCHEME)
GENERATE[aesni-x86_64.s]=asm/aesni-x86_64.pl $(PERLASM_SCHEME)
GENERATE[aesni-sha1-x86_64.s]=asm/aesni-sha1-x86_64.pl $(PERLASM_SCHEME)
GENERATE[aesni-sha256-x86_64.s]=asm/aesni-sha256-x86_64.pl $(PERLASM_SCHEME)
GENERATE[aesni-mb-x86_64.s]=asm/aesni-mb-x86_64.pl $(PERLASM_SCHEME)
GENERATE[aes-sparcv9.S]=asm/aes-sparcv9.pl $(PERLASM_SCHEME)
INCLUDE[aes-sparcv9.o]=..
GENERATE[aest4-sparcv9.S]=asm/aest4-sparcv9.pl $(PERLASM_SCHEME)
INCLUDE[aest4-sparcv9.o]=..
DEPEND[aest4-sparcv9.S]=../perlasm/sparcv9_modes.pl
GENERATE[aesfx-sparcv9.S]=asm/aesfx-sparcv9.pl $(PERLASM_SCHEME)
INCLUDE[aesfx-sparcv9.o]=..
GENERATE[aes-ppc.s]=asm/aes-ppc.pl $(PERLASM_SCHEME)
GENERATE[vpaes-ppc.s]=asm/vpaes-ppc.pl $(PERLASM_SCHEME)
GENERATE[aesp8-ppc.s]=asm/aesp8-ppc.pl $(PERLASM_SCHEME)
GENERATE[aes-parisc.s]=asm/aes-parisc.pl $(PERLASM_SCHEME)
GENERATE[aes-mips.S]=asm/aes-mips.pl $(PERLASM_SCHEME)
INCLUDE[aes-mips.o]=..
GENERATE[aesv8-armx.S]=asm/aesv8-armx.pl $(PERLASM_SCHEME)
INCLUDE[aesv8-armx.o]=..
GENERATE[vpaes-armv8.S]=asm/vpaes-armv8.pl $(PERLASM_SCHEME)
GENERATE[aes-armv4.S]=asm/aes-armv4.pl $(PERLASM_SCHEME)
INCLUDE[aes-armv4.o]=..
GENERATE[bsaes-armv7.S]=asm/bsaes-armv7.pl $(PERLASM_SCHEME)
INCLUDE[bsaes-armv7.o]=..
GENERATE[aes-s390x.S]=asm/aes-s390x.pl $(PERLASM_SCHEME)
INCLUDE[aes-s390x.o]=..
BEGINRAW[Makefile]
##### AES assembler implementations
# GNU make "catch all"
{- $builddir -}/aes-%.S: {- $sourcedir -}/asm/aes-%.pl
CC="$(CC)" $(PERL) $< $(PERLASM_SCHEME) $@
{- $builddir -}/bsaes-%.S: {- $sourcedir -}/asm/bsaes-%.pl
CC="$(CC)" $(PERL) $< $(PERLASM_SCHEME) $@
ENDRAW[Makefile]

View file

@ -0,0 +1,257 @@
#! /usr/bin/env perl
# Copyright 2010-2016 The OpenSSL Project Authors. All Rights Reserved.
#
# Licensed under the OpenSSL license (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
$output = pop;
open STDOUT,">$output";
print <<'___';
.text
.set noat
.globl OPENSSL_cpuid_setup
.ent OPENSSL_cpuid_setup
OPENSSL_cpuid_setup:
.frame $30,0,$26
.prologue 0
ret ($26)
.end OPENSSL_cpuid_setup
.globl OPENSSL_wipe_cpu
.ent OPENSSL_wipe_cpu
OPENSSL_wipe_cpu:
.frame $30,0,$26
.prologue 0
clr $1
clr $2
clr $3
clr $4
clr $5
clr $6
clr $7
clr $8
clr $16
clr $17
clr $18
clr $19
clr $20
clr $21
clr $22
clr $23
clr $24
clr $25
clr $27
clr $at
clr $29
fclr $f0
fclr $f1
fclr $f10
fclr $f11
fclr $f12
fclr $f13
fclr $f14
fclr $f15
fclr $f16
fclr $f17
fclr $f18
fclr $f19
fclr $f20
fclr $f21
fclr $f22
fclr $f23
fclr $f24
fclr $f25
fclr $f26
fclr $f27
fclr $f28
fclr $f29
fclr $f30
mov $sp,$0
ret ($26)
.end OPENSSL_wipe_cpu
.globl OPENSSL_atomic_add
.ent OPENSSL_atomic_add
OPENSSL_atomic_add:
.frame $30,0,$26
.prologue 0
1: ldl_l $0,0($16)
addl $0,$17,$1
stl_c $1,0($16)
beq $1,1b
addl $0,$17,$0
ret ($26)
.end OPENSSL_atomic_add
.globl OPENSSL_rdtsc
.ent OPENSSL_rdtsc
OPENSSL_rdtsc:
.frame $30,0,$26
.prologue 0
rpcc $0
ret ($26)
.end OPENSSL_rdtsc
.globl OPENSSL_cleanse
.ent OPENSSL_cleanse
OPENSSL_cleanse:
.frame $30,0,$26
.prologue 0
beq $17,.Ldone
and $16,7,$0
bic $17,7,$at
beq $at,.Little
beq $0,.Laligned
.Little:
subq $0,8,$0
ldq_u $1,0($16)
mov $16,$2
.Lalign:
mskbl $1,$16,$1
lda $16,1($16)
subq $17,1,$17
addq $0,1,$0
beq $17,.Lout
bne $0,.Lalign
.Lout: stq_u $1,0($2)
beq $17,.Ldone
bic $17,7,$at
beq $at,.Little
.Laligned:
stq $31,0($16)
subq $17,8,$17
lda $16,8($16)
bic $17,7,$at
bne $at,.Laligned
bne $17,.Little
.Ldone: ret ($26)
.end OPENSSL_cleanse
.globl CRYPTO_memcmp
.ent CRYPTO_memcmp
CRYPTO_memcmp:
.frame $30,0,$26
.prologue 0
xor $0,$0,$0
beq $18,.Lno_data
xor $1,$1,$1
nop
.Loop_cmp:
ldq_u $2,0($16)
subq $18,1,$18
ldq_u $3,0($17)
extbl $2,$16,$2
lda $16,1($16)
extbl $3,$17,$3
lda $17,1($17)
xor $3,$2,$2
or $2,$0,$0
bne $18,.Loop_cmp
subq $31,$0,$0
srl $0,63,$0
.Lno_data:
ret ($26)
.end CRYPTO_memcmp
___
{
my ($out,$cnt,$max)=("\$16","\$17","\$18");
my ($tick,$lasttick)=("\$19","\$20");
my ($diff,$lastdiff)=("\$21","\$22");
my ($v0,$ra,$sp,$zero)=("\$0","\$26","\$30","\$31");
print <<___;
.globl OPENSSL_instrument_bus
.ent OPENSSL_instrument_bus
OPENSSL_instrument_bus:
.frame $sp,0,$ra
.prologue 0
mov $cnt,$v0
rpcc $lasttick
mov 0,$diff
ecb ($out)
ldl_l $tick,0($out)
addl $diff,$tick,$tick
mov $tick,$diff
stl_c $tick,0($out)
stl $diff,0($out)
.Loop: rpcc $tick
subq $tick,$lasttick,$diff
mov $tick,$lasttick
ecb ($out)
ldl_l $tick,0($out)
addl $diff,$tick,$tick
mov $tick,$diff
stl_c $tick,0($out)
stl $diff,0($out)
subl $cnt,1,$cnt
lda $out,4($out)
bne $cnt,.Loop
ret ($ra)
.end OPENSSL_instrument_bus
.globl OPENSSL_instrument_bus2
.ent OPENSSL_instrument_bus2
OPENSSL_instrument_bus2:
.frame $sp,0,$ra
.prologue 0
mov $cnt,$v0
rpcc $lasttick
mov 0,$diff
ecb ($out)
ldl_l $tick,0($out)
addl $diff,$tick,$tick
mov $tick,$diff
stl_c $tick,0($out)
stl $diff,0($out)
rpcc $tick
subq $tick,$lasttick,$diff
mov $tick,$lasttick
mov $diff,$lastdiff
.Loop2:
ecb ($out)
ldl_l $tick,0($out)
addl $diff,$tick,$tick
mov $tick,$diff
stl_c $tick,0($out)
stl $diff,0($out)
subl $max,1,$max
beq $max,.Ldone2
rpcc $tick
subq $tick,$lasttick,$diff
mov $tick,$lasttick
subq $lastdiff,$diff,$tick
mov $diff,$lastdiff
cmovne $tick,1,$tick
subl $cnt,$tick,$cnt
s4addq $tick,$out,$out
bne $cnt,.Loop2
.Ldone2:
subl $v0,$cnt,$v0
ret ($ra)
.end OPENSSL_instrument_bus2
___
}
close STDOUT;

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,4 @@
LIBS=../../libcrypto
SOURCE[../../libcrypto]=\
aria.c

View file

@ -0,0 +1,147 @@
#! /usr/bin/env perl
# Copyright 2015-2018 The OpenSSL Project Authors. All Rights Reserved.
#
# Licensed under the OpenSSL license (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
$flavour = shift;
$output = shift;
$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
( $xlate="${dir}arm-xlate.pl" and -f $xlate ) or
( $xlate="${dir}perlasm/arm-xlate.pl" and -f $xlate) or
die "can't locate arm-xlate.pl";
open OUT,"| \"$^X\" $xlate $flavour $output";
*STDOUT=*OUT;
$code.=<<___;
#include "arm_arch.h"
.text
.arch armv8-a+crypto
.align 5
.globl _armv7_neon_probe
.type _armv7_neon_probe,%function
_armv7_neon_probe:
orr v15.16b, v15.16b, v15.16b
ret
.size _armv7_neon_probe,.-_armv7_neon_probe
.globl _armv7_tick
.type _armv7_tick,%function
_armv7_tick:
#ifdef __APPLE__
mrs x0, CNTPCT_EL0
#else
mrs x0, CNTVCT_EL0
#endif
ret
.size _armv7_tick,.-_armv7_tick
.globl _armv8_aes_probe
.type _armv8_aes_probe,%function
_armv8_aes_probe:
aese v0.16b, v0.16b
ret
.size _armv8_aes_probe,.-_armv8_aes_probe
.globl _armv8_sha1_probe
.type _armv8_sha1_probe,%function
_armv8_sha1_probe:
sha1h s0, s0
ret
.size _armv8_sha1_probe,.-_armv8_sha1_probe
.globl _armv8_sha256_probe
.type _armv8_sha256_probe,%function
_armv8_sha256_probe:
sha256su0 v0.4s, v0.4s
ret
.size _armv8_sha256_probe,.-_armv8_sha256_probe
.globl _armv8_pmull_probe
.type _armv8_pmull_probe,%function
_armv8_pmull_probe:
pmull v0.1q, v0.1d, v0.1d
ret
.size _armv8_pmull_probe,.-_armv8_pmull_probe
.globl _armv8_sha512_probe
.type _armv8_sha512_probe,%function
_armv8_sha512_probe:
.long 0xcec08000 // sha512su0 v0.2d,v0.2d
ret
.size _armv8_sha512_probe,.-_armv8_sha512_probe
.globl OPENSSL_cleanse
.type OPENSSL_cleanse,%function
.align 5
OPENSSL_cleanse:
cbz x1,.Lret // len==0?
cmp x1,#15
b.hi .Lot // len>15
nop
.Little:
strb wzr,[x0],#1 // store byte-by-byte
subs x1,x1,#1
b.ne .Little
.Lret: ret
.align 4
.Lot: tst x0,#7
b.eq .Laligned // inp is aligned
strb wzr,[x0],#1 // store byte-by-byte
sub x1,x1,#1
b .Lot
.align 4
.Laligned:
str xzr,[x0],#8 // store word-by-word
sub x1,x1,#8
tst x1,#-8
b.ne .Laligned // len>=8
cbnz x1,.Little // len!=0?
ret
.size OPENSSL_cleanse,.-OPENSSL_cleanse
.globl CRYPTO_memcmp
.type CRYPTO_memcmp,%function
.align 4
CRYPTO_memcmp:
eor w3,w3,w3
cbz x2,.Lno_data // len==0?
cmp x2,#16
b.ne .Loop_cmp
ldp x8,x9,[x0]
ldp x10,x11,[x1]
eor x8,x8,x10
eor x9,x9,x11
orr x8,x8,x9
mov x0,#1
cmp x8,#0
csel x0,xzr,x0,eq
ret
.align 4
.Loop_cmp:
ldrb w4,[x0],#1
ldrb w5,[x1],#1
eor w4,w4,w5
orr w3,w3,w4
subs x2,x2,#1
b.ne .Loop_cmp
.Lno_data:
neg w0,w3
lsr w0,w0,#31
ret
.size CRYPTO_memcmp,.-CRYPTO_memcmp
___
print $code;
close STDOUT;

View file

@ -0,0 +1,84 @@
/*
* Copyright 2011-2018 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#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_architectures[] 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
# 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)
# define ARMV8_SHA512 (1<<6)
#endif

View file

@ -0,0 +1,214 @@
/*
* Copyright 2011-2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <setjmp.h>
#include <signal.h>
#include <openssl/crypto.h>
#include "internal/cryptlib.h"
#include "arm_arch.h"
unsigned int OPENSSL_armcap_P = 0;
#if __ARM_MAX_ARCH__<7
void OPENSSL_cpuid_setup(void)
{
}
uint32_t 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);
}
/*
* 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);
# ifdef __aarch64__
void _armv8_sha512_probe(void);
# endif
uint32_t _armv7_tick(void);
uint32_t OPENSSL_rdtsc(void)
{
if (OPENSSL_armcap_P & ARMV7_TICK)
return _armv7_tick();
else
return 0;
}
# if defined(__GNUC__) && __GNUC__>=2
void OPENSSL_cpuid_setup(void) __attribute__ ((constructor));
# endif
# if defined(__GLIBC__) && defined(__GLIBC_PREREQ)
# if __GLIBC_PREREQ(2, 16)
# include <sys/auxv.h>
# define OSSL_IMPLEMENT_GETAUXVAL
# endif
# endif
/*
* ARM puts 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)
# define HWCAP_CE_SHA512 (1 << 21)
# endif
void OPENSSL_cpuid_setup(void)
{
const 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;
}
# if defined(__APPLE__) && !defined(__aarch64__)
/*
* Capability probing by catching SIGILL appears to be problematic
* on iOS. But since Apple universe is "monocultural", it's actually
* possible to simply set pre-defined processor capability mask.
*/
if (1) {
OPENSSL_armcap_P = ARMV7_NEON;
return;
}
/*
* One could do same even for __aarch64__ iOS builds. It's not done
* exclusively for reasons of keeping code unified across platforms.
* Unified code works because it never triggers SIGILL on Apple
* devices...
*/
# endif
OPENSSL_armcap_P = 0;
# ifdef OSSL_IMPLEMENT_GETAUXVAL
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;
# ifdef __aarch64__
if (hwcap & HWCAP_CE_SHA512)
OPENSSL_armcap_P |= ARMV8_SHA512;
# endif
}
# endif
sigfillset(&all_masked);
sigdelset(&all_masked, SIGILL);
sigdelset(&all_masked, SIGTRAP);
sigdelset(&all_masked, SIGFPE);
sigdelset(&all_masked, SIGBUS);
sigdelset(&all_masked, SIGSEGV);
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 we used getauxval, we already have all the values */
# ifndef OSSL_IMPLEMENT_GETAUXVAL
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 defined(__aarch64__) && !defined(__APPLE__)
if (sigsetjmp(ill_jmp, 1) == 0) {
_armv8_sha512_probe();
OPENSSL_armcap_P |= ARMV8_SHA512;
}
# endif
}
# endif
/* Things that getauxval didn't tell us */
if (sigsetjmp(ill_jmp, 1) == 0) {
_armv7_tick();
OPENSSL_armcap_P |= ARMV7_TICK;
}
sigaction(SIGILL, &ill_oact, NULL);
sigprocmask(SIG_SETMASK, &oset, NULL);
}
#endif

View file

@ -0,0 +1,296 @@
#! /usr/bin/env perl
# Copyright 2015-2018 The OpenSSL Project Authors. All Rights Reserved.
#
# Licensed under the OpenSSL license (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
$flavour = shift;
$output = shift;
$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
( $xlate="${dir}arm-xlate.pl" and -f $xlate ) or
( $xlate="${dir}perlasm/arm-xlate.pl" and -f $xlate) or
die "can't locate arm-xlate.pl";
open OUT,"| \"$^X\" $xlate $flavour $output";
*STDOUT=*OUT;
$code.=<<___;
#include "arm_arch.h"
.text
#if defined(__thumb2__) && !defined(__APPLE__)
.syntax unified
.thumb
#else
.code 32
#undef __thumb2__
#endif
.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
#ifdef __thumb2__
itt hs
#endif
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
.global CRYPTO_memcmp
.type CRYPTO_memcmp,%function
.align 4
CRYPTO_memcmp:
eor ip,ip,ip
cmp r2,#0
beq .Lno_data
stmdb sp!,{r4,r5}
.Loop_cmp:
ldrb r4,[r0],#1
ldrb r5,[r1],#1
eor r4,r4,r5
orr ip,ip,r4
subs r2,r2,#1
bne .Loop_cmp
ldmia sp!,{r4,r5}
.Lno_data:
rsb r0,ip,#0
mov r0,r0,lsr#31
#if __ARM_ARCH__>=5
bx lr
#else
tst lr,#1
moveq pc,lr
.word 0xe12fff1e @ bx lr
#endif
.size CRYPTO_memcmp,.-CRYPTO_memcmp
#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:
#ifdef __APPLE__
mrrc p15,0,r0,r1,c14 @ CNTPCT
#else
mrrc p15,1,r0,r1,c14 @ CNTVCT
#endif
bx lr
.size _armv7_tick,.-_armv7_tick
.global _armv8_aes_probe
.type _armv8_aes_probe,%function
_armv8_aes_probe:
#if defined(__thumb2__) && !defined(__APPLE__)
.byte 0xb0,0xff,0x00,0x03 @ aese.8 q0,q0
#else
.byte 0x00,0x03,0xb0,0xf3 @ aese.8 q0,q0
#endif
bx lr
.size _armv8_aes_probe,.-_armv8_aes_probe
.global _armv8_sha1_probe
.type _armv8_sha1_probe,%function
_armv8_sha1_probe:
#if defined(__thumb2__) && !defined(__APPLE__)
.byte 0x00,0xef,0x40,0x0c @ sha1c.32 q0,q0,q0
#else
.byte 0x40,0x0c,0x00,0xf2 @ sha1c.32 q0,q0,q0
#endif
bx lr
.size _armv8_sha1_probe,.-_armv8_sha1_probe
.global _armv8_sha256_probe
.type _armv8_sha256_probe,%function
_armv8_sha256_probe:
#if defined(__thumb2__) && !defined(__APPLE__)
.byte 0x00,0xff,0x40,0x0c @ sha256h.32 q0,q0,q0
#else
.byte 0x40,0x0c,0x00,0xf3 @ sha256h.32 q0,q0,q0
#endif
bx lr
.size _armv8_sha256_probe,.-_armv8_sha256_probe
.global _armv8_pmull_probe
.type _armv8_pmull_probe,%function
_armv8_pmull_probe:
#if defined(__thumb2__) && !defined(__APPLE__)
.byte 0xa0,0xef,0x00,0x0e @ vmull.p64 q0,d0,d0
#else
.byte 0x00,0x0e,0xa0,0xf2 @ vmull.p64 q0,d0,d0
#endif
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]
#ifdef __APPLE__
ldr r0,[r0]
#endif
#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-.
#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
.comm OPENSSL_armcap_P,4,4
.hidden OPENSSL_armcap_P
___
print $code;
close STDOUT;

View file

@ -0,0 +1,216 @@
/*
* Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <limits.h>
#include <stdio.h>
#include "internal/cryptlib.h"
#include <openssl/asn1.h>
#include "asn1_locl.h"
int ASN1_BIT_STRING_set(ASN1_BIT_STRING *x, unsigned char *d, int len)
{
return ASN1_STRING_set(x, d, len);
}
int i2c_ASN1_BIT_STRING(ASN1_BIT_STRING *a, unsigned char **pp)
{
int ret, j, bits, len;
unsigned char *p, *d;
if (a == NULL)
return 0;
len = a->length;
if (len > 0) {
if (a->flags & ASN1_STRING_FLAG_BITS_LEFT) {
bits = (int)a->flags & 0x07;
} else {
for (; len > 0; len--) {
if (a->data[len - 1])
break;
}
j = a->data[len - 1];
if (j & 0x01)
bits = 0;
else if (j & 0x02)
bits = 1;
else if (j & 0x04)
bits = 2;
else if (j & 0x08)
bits = 3;
else if (j & 0x10)
bits = 4;
else if (j & 0x20)
bits = 5;
else if (j & 0x40)
bits = 6;
else if (j & 0x80)
bits = 7;
else
bits = 0; /* should not happen */
}
} else
bits = 0;
ret = 1 + len;
if (pp == NULL)
return ret;
p = *pp;
*(p++) = (unsigned char)bits;
d = a->data;
if (len > 0) {
memcpy(p, d, len);
p += len;
p[-1] &= (0xff << bits);
}
*pp = p;
return ret;
}
ASN1_BIT_STRING *c2i_ASN1_BIT_STRING(ASN1_BIT_STRING **a,
const unsigned char **pp, long len)
{
ASN1_BIT_STRING *ret = NULL;
const unsigned char *p;
unsigned char *s;
int i;
if (len < 1) {
i = ASN1_R_STRING_TOO_SHORT;
goto err;
}
if (len > INT_MAX) {
i = ASN1_R_STRING_TOO_LONG;
goto err;
}
if ((a == NULL) || ((*a) == NULL)) {
if ((ret = ASN1_BIT_STRING_new()) == NULL)
return NULL;
} else
ret = (*a);
p = *pp;
i = *(p++);
if (i > 7) {
i = ASN1_R_INVALID_BIT_STRING_BITS_LEFT;
goto err;
}
/*
* We do this to preserve the settings. If we modify the settings, via
* the _set_bit function, we will recalculate on output
*/
ret->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07); /* clear */
ret->flags |= (ASN1_STRING_FLAG_BITS_LEFT | i); /* set */
if (len-- > 1) { /* using one because of the bits left byte */
s = OPENSSL_malloc((int)len);
if (s == NULL) {
i = ERR_R_MALLOC_FAILURE;
goto err;
}
memcpy(s, p, (int)len);
s[len - 1] &= (0xff << i);
p += len;
} else
s = NULL;
ret->length = (int)len;
OPENSSL_free(ret->data);
ret->data = s;
ret->type = V_ASN1_BIT_STRING;
if (a != NULL)
(*a) = ret;
*pp = p;
return ret;
err:
ASN1err(ASN1_F_C2I_ASN1_BIT_STRING, i);
if ((a == NULL) || (*a != ret))
ASN1_BIT_STRING_free(ret);
return NULL;
}
/*
* These next 2 functions from Goetz Babin-Ebell.
*/
int ASN1_BIT_STRING_set_bit(ASN1_BIT_STRING *a, int n, int value)
{
int w, v, iv;
unsigned char *c;
w = n / 8;
v = 1 << (7 - (n & 0x07));
iv = ~v;
if (!value)
v = 0;
if (a == NULL)
return 0;
a->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07); /* clear, set on write */
if ((a->length < (w + 1)) || (a->data == NULL)) {
if (!value)
return 1; /* Don't need to set */
c = OPENSSL_clear_realloc(a->data, a->length, w + 1);
if (c == NULL) {
ASN1err(ASN1_F_ASN1_BIT_STRING_SET_BIT, ERR_R_MALLOC_FAILURE);
return 0;
}
if (w + 1 - a->length > 0)
memset(c + a->length, 0, w + 1 - a->length);
a->data = c;
a->length = w + 1;
}
a->data[w] = ((a->data[w]) & iv) | v;
while ((a->length > 0) && (a->data[a->length - 1] == 0))
a->length--;
return 1;
}
int ASN1_BIT_STRING_get_bit(const ASN1_BIT_STRING *a, int n)
{
int w, v;
w = n / 8;
v = 1 << (7 - (n & 0x07));
if ((a == NULL) || (a->length < (w + 1)) || (a->data == NULL))
return 0;
return ((a->data[w] & v) != 0);
}
/*
* Checks if the given bit string contains only bits specified by
* the flags vector. Returns 0 if there is at least one bit set in 'a'
* which is not specified in 'flags', 1 otherwise.
* 'len' is the length of 'flags'.
*/
int ASN1_BIT_STRING_check(const ASN1_BIT_STRING *a,
const unsigned char *flags, int flags_len)
{
int i, ok;
/* Check if there is one bit set at all. */
if (!a || !a->data)
return 1;
/*
* Check each byte of the internal representation of the bit string.
*/
ok = 1;
for (i = 0; i < a->length && ok; ++i) {
unsigned char mask = i < flags_len ? ~flags[i] : 0xff;
/* We are done if there is an unneeded bit set. */
ok = (a->data[i] & mask) == 0;
}
return ok;
}

View file

@ -0,0 +1,234 @@
/*
* Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <stdio.h>
#include <limits.h>
#include "internal/cryptlib.h"
#include "internal/numbers.h"
#include <openssl/buffer.h>
#include <openssl/asn1.h>
#include "internal/asn1_int.h"
#ifndef NO_OLD_ASN1
# ifndef OPENSSL_NO_STDIO
void *ASN1_d2i_fp(void *(*xnew) (void), d2i_of_void *d2i, FILE *in, void **x)
{
BIO *b;
void *ret;
if ((b = BIO_new(BIO_s_file())) == NULL) {
ASN1err(ASN1_F_ASN1_D2I_FP, ERR_R_BUF_LIB);
return NULL;
}
BIO_set_fp(b, in, BIO_NOCLOSE);
ret = ASN1_d2i_bio(xnew, d2i, b, x);
BIO_free(b);
return ret;
}
# endif
void *ASN1_d2i_bio(void *(*xnew) (void), d2i_of_void *d2i, BIO *in, void **x)
{
BUF_MEM *b = NULL;
const unsigned char *p;
void *ret = NULL;
int len;
len = asn1_d2i_read_bio(in, &b);
if (len < 0)
goto err;
p = (unsigned char *)b->data;
ret = d2i(x, &p, len);
err:
BUF_MEM_free(b);
return ret;
}
#endif
void *ASN1_item_d2i_bio(const ASN1_ITEM *it, BIO *in, void *x)
{
BUF_MEM *b = NULL;
const unsigned char *p;
void *ret = NULL;
int len;
len = asn1_d2i_read_bio(in, &b);
if (len < 0)
goto err;
p = (const unsigned char *)b->data;
ret = ASN1_item_d2i(x, &p, len, it);
err:
BUF_MEM_free(b);
return ret;
}
#ifndef OPENSSL_NO_STDIO
void *ASN1_item_d2i_fp(const ASN1_ITEM *it, FILE *in, void *x)
{
BIO *b;
char *ret;
if ((b = BIO_new(BIO_s_file())) == NULL) {
ASN1err(ASN1_F_ASN1_ITEM_D2I_FP, ERR_R_BUF_LIB);
return NULL;
}
BIO_set_fp(b, in, BIO_NOCLOSE);
ret = ASN1_item_d2i_bio(it, b, x);
BIO_free(b);
return ret;
}
#endif
#define HEADER_SIZE 8
#define ASN1_CHUNK_INITIAL_SIZE (16 * 1024)
int asn1_d2i_read_bio(BIO *in, BUF_MEM **pb)
{
BUF_MEM *b;
unsigned char *p;
int i;
size_t want = HEADER_SIZE;
uint32_t eos = 0;
size_t off = 0;
size_t len = 0;
const unsigned char *q;
long slen;
int inf, tag, xclass;
b = BUF_MEM_new();
if (b == NULL) {
ASN1err(ASN1_F_ASN1_D2I_READ_BIO, ERR_R_MALLOC_FAILURE);
return -1;
}
ERR_clear_error();
for (;;) {
if (want >= (len - off)) {
want -= (len - off);
if (len + want < len || !BUF_MEM_grow_clean(b, len + want)) {
ASN1err(ASN1_F_ASN1_D2I_READ_BIO, ERR_R_MALLOC_FAILURE);
goto err;
}
i = BIO_read(in, &(b->data[len]), want);
if ((i < 0) && ((len - off) == 0)) {
ASN1err(ASN1_F_ASN1_D2I_READ_BIO, ASN1_R_NOT_ENOUGH_DATA);
goto err;
}
if (i > 0) {
if (len + i < len) {
ASN1err(ASN1_F_ASN1_D2I_READ_BIO, ASN1_R_TOO_LONG);
goto err;
}
len += i;
}
}
/* else data already loaded */
p = (unsigned char *)&(b->data[off]);
q = p;
inf = ASN1_get_object(&q, &slen, &tag, &xclass, len - off);
if (inf & 0x80) {
unsigned long e;
e = ERR_GET_REASON(ERR_peek_error());
if (e != ASN1_R_TOO_LONG)
goto err;
else
ERR_clear_error(); /* clear error */
}
i = q - p; /* header length */
off += i; /* end of data */
if (inf & 1) {
/* no data body so go round again */
if (eos == UINT32_MAX) {
ASN1err(ASN1_F_ASN1_D2I_READ_BIO, ASN1_R_HEADER_TOO_LONG);
goto err;
}
eos++;
want = HEADER_SIZE;
} else if (eos && (slen == 0) && (tag == V_ASN1_EOC)) {
/* eos value, so go back and read another header */
eos--;
if (eos == 0)
break;
else
want = HEADER_SIZE;
} else {
/* suck in slen bytes of data */
want = slen;
if (want > (len - off)) {
size_t chunk_max = ASN1_CHUNK_INITIAL_SIZE;
want -= (len - off);
if (want > INT_MAX /* BIO_read takes an int length */ ||
len + want < len) {
ASN1err(ASN1_F_ASN1_D2I_READ_BIO, ASN1_R_TOO_LONG);
goto err;
}
while (want > 0) {
/*
* Read content in chunks of increasing size
* so we can return an error for EOF without
* having to allocate the entire content length
* in one go.
*/
size_t chunk = want > chunk_max ? chunk_max : want;
if (!BUF_MEM_grow_clean(b, len + chunk)) {
ASN1err(ASN1_F_ASN1_D2I_READ_BIO, ERR_R_MALLOC_FAILURE);
goto err;
}
want -= chunk;
while (chunk > 0) {
i = BIO_read(in, &(b->data[len]), chunk);
if (i <= 0) {
ASN1err(ASN1_F_ASN1_D2I_READ_BIO,
ASN1_R_NOT_ENOUGH_DATA);
goto err;
}
/*
* This can't overflow because |len+want| didn't
* overflow.
*/
len += i;
chunk -= i;
}
if (chunk_max < INT_MAX/2)
chunk_max *= 2;
}
}
if (off + slen < off) {
ASN1err(ASN1_F_ASN1_D2I_READ_BIO, ASN1_R_TOO_LONG);
goto err;
}
off += slen;
if (eos == 0) {
break;
} else
want = HEADER_SIZE;
}
}
if (off > INT_MAX) {
ASN1err(ASN1_F_ASN1_D2I_READ_BIO, ASN1_R_TOO_LONG);
goto err;
}
*pb = b;
return off;
err:
BUF_MEM_free(b);
return -1;
}

View file

@ -0,0 +1,67 @@
/*
* Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <stdio.h>
#include <time.h>
#include <sys/types.h>
#include "internal/cryptlib.h"
#include <openssl/err.h>
#include <openssl/evp.h>
#include <openssl/buffer.h>
#include <openssl/x509.h>
#ifndef NO_ASN1_OLD
int ASN1_digest(i2d_of_void *i2d, const EVP_MD *type, char *data,
unsigned char *md, unsigned int *len)
{
int inl;
unsigned char *str, *p;
inl = i2d(data, NULL);
if (inl <= 0) {
ASN1err(ASN1_F_ASN1_DIGEST, ERR_R_INTERNAL_ERROR);
return 0;
}
if ((str = OPENSSL_malloc(inl)) == NULL) {
ASN1err(ASN1_F_ASN1_DIGEST, ERR_R_MALLOC_FAILURE);
return 0;
}
p = str;
i2d(data, &p);
if (!EVP_Digest(str, inl, 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;
}

View file

@ -0,0 +1,68 @@
/*
* Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <stdio.h>
#include "internal/cryptlib.h"
#include <openssl/asn1.h>
#ifndef NO_OLD_ASN1
void *ASN1_dup(i2d_of_void *i2d, d2i_of_void *d2i, void *x)
{
unsigned char *b, *p;
const unsigned char *p2;
int i;
char *ret;
if (x == NULL)
return NULL;
i = i2d(x, NULL);
b = OPENSSL_malloc(i + 10);
if (b == NULL) {
ASN1err(ASN1_F_ASN1_DUP, ERR_R_MALLOC_FAILURE);
return NULL;
}
p = b;
i = i2d(x, &p);
p2 = b;
ret = d2i(NULL, &p2, i);
OPENSSL_free(b);
return ret;
}
#endif
/*
* ASN1_ITEM version of dup: this follows the model above except we don't
* need to allocate the buffer. At some point this could be rewritten to
* directly dup the underlying structure instead of doing and encode and
* decode.
*/
void *ASN1_item_dup(const ASN1_ITEM *it, void *x)
{
unsigned char *b = NULL;
const unsigned char *p;
long i;
void *ret;
if (x == NULL)
return NULL;
i = ASN1_item_i2d(x, &b, it);
if (b == NULL) {
ASN1err(ASN1_F_ASN1_ITEM_DUP, ERR_R_MALLOC_FAILURE);
return NULL;
}
p = b;
ret = ASN1_item_d2i(NULL, &p, i, it);
OPENSSL_free(b);
return ret;
}

View file

@ -0,0 +1,82 @@
/*
* Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
/*
* GENERALIZEDTIME implementation. Based on UTCTIME
*/
#include <stdio.h>
#include <time.h>
#include "internal/cryptlib.h"
#include <openssl/asn1.h>
#include "asn1_locl.h"
/* This is the primary function used to parse ASN1_GENERALIZEDTIME */
int asn1_generalizedtime_to_tm(struct tm *tm, const ASN1_GENERALIZEDTIME *d)
{
/* wrapper around asn1_time_to_tm */
if (d->type != V_ASN1_GENERALIZEDTIME)
return 0;
return asn1_time_to_tm(tm, d);
}
int ASN1_GENERALIZEDTIME_check(const ASN1_GENERALIZEDTIME *d)
{
return asn1_generalizedtime_to_tm(NULL, d);
}
int ASN1_GENERALIZEDTIME_set_string(ASN1_GENERALIZEDTIME *s, const char *str)
{
ASN1_GENERALIZEDTIME t;
t.type = V_ASN1_GENERALIZEDTIME;
t.length = strlen(str);
t.data = (unsigned char *)str;
t.flags = 0;
if (!ASN1_GENERALIZEDTIME_check(&t))
return 0;
if (s != NULL && !ASN1_STRING_copy(s, &t))
return 0;
return 1;
}
ASN1_GENERALIZEDTIME *ASN1_GENERALIZEDTIME_set(ASN1_GENERALIZEDTIME *s,
time_t t)
{
return ASN1_GENERALIZEDTIME_adj(s, t, 0, 0);
}
ASN1_GENERALIZEDTIME *ASN1_GENERALIZEDTIME_adj(ASN1_GENERALIZEDTIME *s,
time_t t, int offset_day,
long offset_sec)
{
struct tm *ts;
struct tm data;
ts = OPENSSL_gmtime(&t, &data);
if (ts == NULL)
return NULL;
if (offset_day || offset_sec) {
if (!OPENSSL_gmtime_adj(ts, offset_day, offset_sec))
return NULL;
}
return asn1_time_from_tm(s, ts, V_ASN1_GENERALIZEDTIME);
}
int ASN1_GENERALIZEDTIME_print(BIO *bp, const ASN1_GENERALIZEDTIME *tm)
{
if (tm->type != V_ASN1_GENERALIZEDTIME)
return 0;
return ASN1_TIME_print(bp, tm);
}

View file

@ -0,0 +1,111 @@
/*
* Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <stdio.h>
#include "internal/cryptlib.h"
#include <openssl/buffer.h>
#include <openssl/asn1.h>
#ifndef NO_OLD_ASN1
# ifndef OPENSSL_NO_STDIO
int ASN1_i2d_fp(i2d_of_void *i2d, FILE *out, void *x)
{
BIO *b;
int ret;
if ((b = BIO_new(BIO_s_file())) == NULL) {
ASN1err(ASN1_F_ASN1_I2D_FP, ERR_R_BUF_LIB);
return 0;
}
BIO_set_fp(b, out, BIO_NOCLOSE);
ret = ASN1_i2d_bio(i2d, b, x);
BIO_free(b);
return ret;
}
# endif
int ASN1_i2d_bio(i2d_of_void *i2d, BIO *out, unsigned char *x)
{
char *b;
unsigned char *p;
int i, j = 0, n, ret = 1;
n = i2d(x, NULL);
if (n <= 0)
return 0;
b = OPENSSL_malloc(n);
if (b == NULL) {
ASN1err(ASN1_F_ASN1_I2D_BIO, ERR_R_MALLOC_FAILURE);
return 0;
}
p = (unsigned char *)b;
i2d(x, &p);
for (;;) {
i = BIO_write(out, &(b[j]), n);
if (i == n)
break;
if (i <= 0) {
ret = 0;
break;
}
j += i;
n -= i;
}
OPENSSL_free(b);
return ret;
}
#endif
#ifndef OPENSSL_NO_STDIO
int ASN1_item_i2d_fp(const ASN1_ITEM *it, FILE *out, void *x)
{
BIO *b;
int ret;
if ((b = BIO_new(BIO_s_file())) == NULL) {
ASN1err(ASN1_F_ASN1_ITEM_I2D_FP, ERR_R_BUF_LIB);
return 0;
}
BIO_set_fp(b, out, BIO_NOCLOSE);
ret = ASN1_item_i2d_bio(it, b, x);
BIO_free(b);
return ret;
}
#endif
int ASN1_item_i2d_bio(const ASN1_ITEM *it, BIO *out, void *x)
{
unsigned char *b = NULL;
int i, j = 0, n, ret = 1;
n = ASN1_item_i2d(x, &b, it);
if (b == NULL) {
ASN1err(ASN1_F_ASN1_ITEM_I2D_BIO, ERR_R_MALLOC_FAILURE);
return 0;
}
for (;;) {
i = BIO_write(out, &(b[j]), n);
if (i == n)
break;
if (i <= 0) {
ret = 0;
break;
}
j += i;
n -= i;
}
OPENSSL_free(b);
return ret;
}

View file

@ -0,0 +1,630 @@
/*
* Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <stdio.h>
#include "internal/cryptlib.h"
#include "internal/numbers.h"
#include <limits.h>
#include <openssl/asn1.h>
#include <openssl/bn.h>
#include "asn1_locl.h"
ASN1_INTEGER *ASN1_INTEGER_dup(const ASN1_INTEGER *x)
{
return ASN1_STRING_dup(x);
}
int ASN1_INTEGER_cmp(const ASN1_INTEGER *x, const ASN1_INTEGER *y)
{
int neg, ret;
/* Compare signs */
neg = x->type & V_ASN1_NEG;
if (neg != (y->type & V_ASN1_NEG)) {
if (neg)
return -1;
else
return 1;
}
ret = ASN1_STRING_cmp(x, y);
if (neg)
return -ret;
else
return ret;
}
/*-
* This converts a big endian buffer and sign into its content encoding.
* This is used for INTEGER and ENUMERATED types.
* The internal representation is an ASN1_STRING whose data is a big endian
* representation of the value, ignoring the sign. The sign is determined by
* the type: if type & V_ASN1_NEG is true it is negative, otherwise positive.
*
* Positive integers are no problem: they are almost the same as the DER
* encoding, except if the first byte is >= 0x80 we need to add a zero pad.
*
* Negative integers are a bit trickier...
* The DER representation of negative integers is in 2s complement form.
* The internal form is converted by complementing each octet and finally
* adding one to the result. This can be done less messily with a little trick.
* If the internal form has trailing zeroes then they will become FF by the
* complement and 0 by the add one (due to carry) so just copy as many trailing
* zeros to the destination as there are in the source. The carry will add one
* to the last none zero octet: so complement this octet and add one and finally
* complement any left over until you get to the start of the string.
*
* Padding is a little trickier too. If the first bytes is > 0x80 then we pad
* with 0xff. However if the first byte is 0x80 and one of the following bytes
* is non-zero we pad with 0xff. The reason for this distinction is that 0x80
* followed by optional zeros isn't padded.
*/
/*
* If |pad| is zero, the operation is effectively reduced to memcpy,
* and if |pad| is 0xff, then it performs two's complement, ~dst + 1.
* Note that in latter case sequence of zeros yields itself, and so
* does 0x80 followed by any number of zeros. These properties are
* used elsewhere below...
*/
static void twos_complement(unsigned char *dst, const unsigned char *src,
size_t len, unsigned char pad)
{
unsigned int carry = pad & 1;
/* Begin at the end of the encoding */
dst += len;
src += len;
/* two's complement value: ~value + 1 */
while (len-- != 0) {
*(--dst) = (unsigned char)(carry += *(--src) ^ pad);
carry >>= 8;
}
}
static size_t i2c_ibuf(const unsigned char *b, size_t blen, int neg,
unsigned char **pp)
{
unsigned int pad = 0;
size_t ret, i;
unsigned char *p, pb = 0;
if (b != NULL && blen) {
ret = blen;
i = b[0];
if (!neg && (i > 127)) {
pad = 1;
pb = 0;
} else if (neg) {
pb = 0xFF;
if (i > 128) {
pad = 1;
} else if (i == 128) {
/*
* Special case [of minimal negative for given length]:
* if any other bytes non zero we pad, otherwise we don't.
*/
for (pad = 0, i = 1; i < blen; i++)
pad |= b[i];
pb = pad != 0 ? 0xffU : 0;
pad = pb & 1;
}
}
ret += pad;
} else {
ret = 1;
blen = 0; /* reduce '(b == NULL || blen == 0)' to '(blen == 0)' */
}
if (pp == NULL || (p = *pp) == NULL)
return ret;
/*
* This magically handles all corner cases, such as '(b == NULL ||
* blen == 0)', non-negative value, "negative" zero, 0x80 followed
* by any number of zeros...
*/
*p = pb;
p += pad; /* yes, p[0] can be written twice, but it's little
* price to pay for eliminated branches */
twos_complement(p, b, blen, pb);
*pp += ret;
return ret;
}
/*
* convert content octets into a big endian buffer. Returns the length
* of buffer or 0 on error: for malformed INTEGER. If output buffer is
* NULL just return length.
*/
static size_t c2i_ibuf(unsigned char *b, int *pneg,
const unsigned char *p, size_t plen)
{
int neg, pad;
/* Zero content length is illegal */
if (plen == 0) {
ASN1err(ASN1_F_C2I_IBUF, ASN1_R_ILLEGAL_ZERO_CONTENT);
return 0;
}
neg = p[0] & 0x80;
if (pneg)
*pneg = neg;
/* Handle common case where length is 1 octet separately */
if (plen == 1) {
if (b != NULL) {
if (neg)
b[0] = (p[0] ^ 0xFF) + 1;
else
b[0] = p[0];
}
return 1;
}
pad = 0;
if (p[0] == 0) {
pad = 1;
} else if (p[0] == 0xFF) {
size_t i;
/*
* Special case [of "one less minimal negative" for given length]:
* if any other bytes non zero it was padded, otherwise not.
*/
for (pad = 0, i = 1; i < plen; i++)
pad |= p[i];
pad = pad != 0 ? 1 : 0;
}
/* reject illegal padding: first two octets MSB can't match */
if (pad && (neg == (p[1] & 0x80))) {
ASN1err(ASN1_F_C2I_IBUF, ASN1_R_ILLEGAL_PADDING);
return 0;
}
/* skip over pad */
p += pad;
plen -= pad;
if (b != NULL)
twos_complement(b, p, plen, neg ? 0xffU : 0);
return plen;
}
int i2c_ASN1_INTEGER(ASN1_INTEGER *a, unsigned char **pp)
{
return i2c_ibuf(a->data, a->length, a->type & V_ASN1_NEG, pp);
}
/* Convert big endian buffer into uint64_t, return 0 on error */
static int asn1_get_uint64(uint64_t *pr, const unsigned char *b, size_t blen)
{
size_t i;
uint64_t r;
if (blen > sizeof(*pr)) {
ASN1err(ASN1_F_ASN1_GET_UINT64, ASN1_R_TOO_LARGE);
return 0;
}
if (b == NULL)
return 0;
for (r = 0, i = 0; i < blen; i++) {
r <<= 8;
r |= b[i];
}
*pr = r;
return 1;
}
/*
* Write uint64_t to big endian buffer and return offset to first
* written octet. In other words it returns offset in range from 0
* to 7, with 0 denoting 8 written octets and 7 - one.
*/
static size_t asn1_put_uint64(unsigned char b[sizeof(uint64_t)], uint64_t r)
{
size_t off = sizeof(uint64_t);
do {
b[--off] = (unsigned char)r;
} while (r >>= 8);
return off;
}
/*
* Absolute value of INT64_MIN: we can't just use -INT64_MIN as gcc produces
* overflow warnings.
*/
#define ABS_INT64_MIN ((uint64_t)INT64_MAX + (-(INT64_MIN + INT64_MAX)))
/* signed version of asn1_get_uint64 */
static int asn1_get_int64(int64_t *pr, const unsigned char *b, size_t blen,
int neg)
{
uint64_t r;
if (asn1_get_uint64(&r, b, blen) == 0)
return 0;
if (neg) {
if (r <= INT64_MAX) {
/* Most significant bit is guaranteed to be clear, negation
* is guaranteed to be meaningful in platform-neutral sense. */
*pr = -(int64_t)r;
} else if (r == ABS_INT64_MIN) {
/* This never happens if INT64_MAX == ABS_INT64_MIN, e.g.
* on ones'-complement system. */
*pr = (int64_t)(0 - r);
} else {
ASN1err(ASN1_F_ASN1_GET_INT64, ASN1_R_TOO_SMALL);
return 0;
}
} else {
if (r <= INT64_MAX) {
*pr = (int64_t)r;
} else {
ASN1err(ASN1_F_ASN1_GET_INT64, ASN1_R_TOO_LARGE);
return 0;
}
}
return 1;
}
/* Convert ASN1 INTEGER content octets to ASN1_INTEGER structure */
ASN1_INTEGER *c2i_ASN1_INTEGER(ASN1_INTEGER **a, const unsigned char **pp,
long len)
{
ASN1_INTEGER *ret = NULL;
size_t r;
int neg;
r = c2i_ibuf(NULL, NULL, *pp, len);
if (r == 0)
return NULL;
if ((a == NULL) || ((*a) == NULL)) {
ret = ASN1_INTEGER_new();
if (ret == NULL)
return NULL;
ret->type = V_ASN1_INTEGER;
} else
ret = *a;
if (ASN1_STRING_set(ret, NULL, r) == 0)
goto err;
c2i_ibuf(ret->data, &neg, *pp, len);
if (neg)
ret->type |= V_ASN1_NEG;
*pp += len;
if (a != NULL)
(*a) = ret;
return ret;
err:
ASN1err(ASN1_F_C2I_ASN1_INTEGER, ERR_R_MALLOC_FAILURE);
if ((a == NULL) || (*a != ret))
ASN1_INTEGER_free(ret);
return NULL;
}
static int asn1_string_get_int64(int64_t *pr, const ASN1_STRING *a, int itype)
{
if (a == NULL) {
ASN1err(ASN1_F_ASN1_STRING_GET_INT64, ERR_R_PASSED_NULL_PARAMETER);
return 0;
}
if ((a->type & ~V_ASN1_NEG) != itype) {
ASN1err(ASN1_F_ASN1_STRING_GET_INT64, ASN1_R_WRONG_INTEGER_TYPE);
return 0;
}
return asn1_get_int64(pr, a->data, a->length, a->type & V_ASN1_NEG);
}
static int asn1_string_set_int64(ASN1_STRING *a, int64_t r, int itype)
{
unsigned char tbuf[sizeof(r)];
size_t off;
a->type = itype;
if (r < 0) {
/* Most obvious '-r' triggers undefined behaviour for most
* common INT64_MIN. Even though below '0 - (uint64_t)r' can
* appear two's-complement centric, it does produce correct/
* expected result even on one's-complement. This is because
* cast to unsigned has to change bit pattern... */
off = asn1_put_uint64(tbuf, 0 - (uint64_t)r);
a->type |= V_ASN1_NEG;
} else {
off = asn1_put_uint64(tbuf, r);
a->type &= ~V_ASN1_NEG;
}
return ASN1_STRING_set(a, tbuf + off, sizeof(tbuf) - off);
}
static int asn1_string_get_uint64(uint64_t *pr, const ASN1_STRING *a,
int itype)
{
if (a == NULL) {
ASN1err(ASN1_F_ASN1_STRING_GET_UINT64, ERR_R_PASSED_NULL_PARAMETER);
return 0;
}
if ((a->type & ~V_ASN1_NEG) != itype) {
ASN1err(ASN1_F_ASN1_STRING_GET_UINT64, ASN1_R_WRONG_INTEGER_TYPE);
return 0;
}
if (a->type & V_ASN1_NEG) {
ASN1err(ASN1_F_ASN1_STRING_GET_UINT64, ASN1_R_ILLEGAL_NEGATIVE_VALUE);
return 0;
}
return asn1_get_uint64(pr, a->data, a->length);
}
static int asn1_string_set_uint64(ASN1_STRING *a, uint64_t r, int itype)
{
unsigned char tbuf[sizeof(r)];
size_t off;
a->type = itype;
off = asn1_put_uint64(tbuf, r);
return ASN1_STRING_set(a, tbuf + off, sizeof(tbuf) - off);
}
/*
* This is a version of d2i_ASN1_INTEGER that ignores the sign bit of ASN1
* integers: some broken software can encode a positive INTEGER with its MSB
* set as negative (it doesn't add a padding zero).
*/
ASN1_INTEGER *d2i_ASN1_UINTEGER(ASN1_INTEGER **a, const unsigned char **pp,
long length)
{
ASN1_INTEGER *ret = NULL;
const unsigned char *p;
unsigned char *s;
long len;
int inf, tag, xclass;
int i;
if ((a == NULL) || ((*a) == NULL)) {
if ((ret = ASN1_INTEGER_new()) == NULL)
return NULL;
ret->type = V_ASN1_INTEGER;
} else
ret = (*a);
p = *pp;
inf = ASN1_get_object(&p, &len, &tag, &xclass, length);
if (inf & 0x80) {
i = ASN1_R_BAD_OBJECT_HEADER;
goto err;
}
if (tag != V_ASN1_INTEGER) {
i = ASN1_R_EXPECTING_AN_INTEGER;
goto err;
}
/*
* We must OPENSSL_malloc stuff, even for 0 bytes otherwise it signifies
* a missing NULL parameter.
*/
s = OPENSSL_malloc((int)len + 1);
if (s == NULL) {
i = ERR_R_MALLOC_FAILURE;
goto err;
}
ret->type = V_ASN1_INTEGER;
if (len) {
if ((*p == 0) && (len != 1)) {
p++;
len--;
}
memcpy(s, p, (int)len);
p += len;
}
OPENSSL_free(ret->data);
ret->data = s;
ret->length = (int)len;
if (a != NULL)
(*a) = ret;
*pp = p;
return ret;
err:
ASN1err(ASN1_F_D2I_ASN1_UINTEGER, i);
if ((a == NULL) || (*a != ret))
ASN1_INTEGER_free(ret);
return NULL;
}
static ASN1_STRING *bn_to_asn1_string(const BIGNUM *bn, ASN1_STRING *ai,
int atype)
{
ASN1_INTEGER *ret;
int len;
if (ai == NULL) {
ret = ASN1_STRING_type_new(atype);
} else {
ret = ai;
ret->type = atype;
}
if (ret == NULL) {
ASN1err(ASN1_F_BN_TO_ASN1_STRING, ERR_R_NESTED_ASN1_ERROR);
goto err;
}
if (BN_is_negative(bn) && !BN_is_zero(bn))
ret->type |= V_ASN1_NEG_INTEGER;
len = BN_num_bytes(bn);
if (len == 0)
len = 1;
if (ASN1_STRING_set(ret, NULL, len) == 0) {
ASN1err(ASN1_F_BN_TO_ASN1_STRING, ERR_R_MALLOC_FAILURE);
goto err;
}
/* Correct zero case */
if (BN_is_zero(bn))
ret->data[0] = 0;
else
len = BN_bn2bin(bn, ret->data);
ret->length = len;
return ret;
err:
if (ret != ai)
ASN1_INTEGER_free(ret);
return NULL;
}
static BIGNUM *asn1_string_to_bn(const ASN1_INTEGER *ai, BIGNUM *bn,
int itype)
{
BIGNUM *ret;
if ((ai->type & ~V_ASN1_NEG) != itype) {
ASN1err(ASN1_F_ASN1_STRING_TO_BN, ASN1_R_WRONG_INTEGER_TYPE);
return NULL;
}
ret = BN_bin2bn(ai->data, ai->length, bn);
if (ret == NULL) {
ASN1err(ASN1_F_ASN1_STRING_TO_BN, ASN1_R_BN_LIB);
return NULL;
}
if (ai->type & V_ASN1_NEG)
BN_set_negative(ret, 1);
return ret;
}
int ASN1_INTEGER_get_int64(int64_t *pr, const ASN1_INTEGER *a)
{
return asn1_string_get_int64(pr, a, V_ASN1_INTEGER);
}
int ASN1_INTEGER_set_int64(ASN1_INTEGER *a, int64_t r)
{
return asn1_string_set_int64(a, r, V_ASN1_INTEGER);
}
int ASN1_INTEGER_get_uint64(uint64_t *pr, const ASN1_INTEGER *a)
{
return asn1_string_get_uint64(pr, a, V_ASN1_INTEGER);
}
int ASN1_INTEGER_set_uint64(ASN1_INTEGER *a, uint64_t r)
{
return asn1_string_set_uint64(a, r, V_ASN1_INTEGER);
}
int ASN1_INTEGER_set(ASN1_INTEGER *a, long v)
{
return ASN1_INTEGER_set_int64(a, v);
}
long ASN1_INTEGER_get(const ASN1_INTEGER *a)
{
int i;
int64_t r;
if (a == NULL)
return 0;
i = ASN1_INTEGER_get_int64(&r, a);
if (i == 0)
return -1;
if (r > LONG_MAX || r < LONG_MIN)
return -1;
return (long)r;
}
ASN1_INTEGER *BN_to_ASN1_INTEGER(const BIGNUM *bn, ASN1_INTEGER *ai)
{
return bn_to_asn1_string(bn, ai, V_ASN1_INTEGER);
}
BIGNUM *ASN1_INTEGER_to_BN(const ASN1_INTEGER *ai, BIGNUM *bn)
{
return asn1_string_to_bn(ai, bn, V_ASN1_INTEGER);
}
int ASN1_ENUMERATED_get_int64(int64_t *pr, const ASN1_ENUMERATED *a)
{
return asn1_string_get_int64(pr, a, V_ASN1_ENUMERATED);
}
int ASN1_ENUMERATED_set_int64(ASN1_ENUMERATED *a, int64_t r)
{
return asn1_string_set_int64(a, r, V_ASN1_ENUMERATED);
}
int ASN1_ENUMERATED_set(ASN1_ENUMERATED *a, long v)
{
return ASN1_ENUMERATED_set_int64(a, v);
}
long ASN1_ENUMERATED_get(const ASN1_ENUMERATED *a)
{
int i;
int64_t r;
if (a == NULL)
return 0;
if ((a->type & ~V_ASN1_NEG) != V_ASN1_ENUMERATED)
return -1;
if (a->length > (int)sizeof(long))
return 0xffffffffL;
i = ASN1_ENUMERATED_get_int64(&r, a);
if (i == 0)
return -1;
if (r > LONG_MAX || r < LONG_MIN)
return -1;
return (long)r;
}
ASN1_ENUMERATED *BN_to_ASN1_ENUMERATED(const BIGNUM *bn, ASN1_ENUMERATED *ai)
{
return bn_to_asn1_string(bn, ai, V_ASN1_ENUMERATED);
}
BIGNUM *ASN1_ENUMERATED_to_BN(const ASN1_ENUMERATED *ai, BIGNUM *bn)
{
return asn1_string_to_bn(ai, bn, V_ASN1_ENUMERATED);
}
/* Internal functions used by x_int64.c */
int c2i_uint64_int(uint64_t *ret, int *neg, const unsigned char **pp, long len)
{
unsigned char buf[sizeof(uint64_t)];
size_t buflen;
buflen = c2i_ibuf(NULL, NULL, *pp, len);
if (buflen == 0)
return 0;
if (buflen > sizeof(uint64_t)) {
ASN1err(ASN1_F_C2I_UINT64_INT, ASN1_R_TOO_LARGE);
return 0;
}
(void)c2i_ibuf(buf, neg, *pp, len);
return asn1_get_uint64(ret, buf, buflen);
}
int i2c_uint64_int(unsigned char *p, uint64_t r, int neg)
{
unsigned char buf[sizeof(uint64_t)];
size_t off;
off = asn1_put_uint64(buf, r);
return i2c_ibuf(buf + off, sizeof(buf) - off, neg, &p);
}

View file

@ -0,0 +1,343 @@
/*
* Copyright 1999-2017 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <stdio.h>
#include "internal/ctype.h"
#include "internal/cryptlib.h"
#include <openssl/asn1.h>
static int traverse_string(const unsigned char *p, int len, int inform,
int (*rfunc) (unsigned long value, void *in),
void *arg);
static int in_utf8(unsigned long value, void *arg);
static int out_utf8(unsigned long value, void *arg);
static int type_str(unsigned long value, void *arg);
static int cpy_asc(unsigned long value, void *arg);
static int cpy_bmp(unsigned long value, void *arg);
static int cpy_univ(unsigned long value, void *arg);
static int cpy_utf8(unsigned long value, void *arg);
/*
* These functions take a string in UTF8, ASCII or multibyte form and a mask
* of permissible ASN1 string types. It then works out the minimal type
* (using the order Numeric < Printable < IA5 < T61 < BMP < Universal < UTF8)
* and creates a string of the correct type with the supplied data. Yes this is
* horrible: it has to be :-( The 'ncopy' form checks minimum and maximum
* size limits too.
*/
int ASN1_mbstring_copy(ASN1_STRING **out, const unsigned char *in, int len,
int inform, unsigned long mask)
{
return ASN1_mbstring_ncopy(out, in, len, inform, mask, 0, 0);
}
int ASN1_mbstring_ncopy(ASN1_STRING **out, const unsigned char *in, int len,
int inform, unsigned long mask,
long minsize, long maxsize)
{
int str_type;
int ret;
char free_out;
int outform, outlen = 0;
ASN1_STRING *dest;
unsigned char *p;
int nchar;
char strbuf[32];
int (*cpyfunc) (unsigned long, void *) = NULL;
if (len == -1)
len = strlen((const char *)in);
if (!mask)
mask = DIRSTRING_TYPE;
/* First do a string check and work out the number of characters */
switch (inform) {
case MBSTRING_BMP:
if (len & 1) {
ASN1err(ASN1_F_ASN1_MBSTRING_NCOPY,
ASN1_R_INVALID_BMPSTRING_LENGTH);
return -1;
}
nchar = len >> 1;
break;
case MBSTRING_UNIV:
if (len & 3) {
ASN1err(ASN1_F_ASN1_MBSTRING_NCOPY,
ASN1_R_INVALID_UNIVERSALSTRING_LENGTH);
return -1;
}
nchar = len >> 2;
break;
case MBSTRING_UTF8:
nchar = 0;
/* This counts the characters and does utf8 syntax checking */
ret = traverse_string(in, len, MBSTRING_UTF8, in_utf8, &nchar);
if (ret < 0) {
ASN1err(ASN1_F_ASN1_MBSTRING_NCOPY, ASN1_R_INVALID_UTF8STRING);
return -1;
}
break;
case MBSTRING_ASC:
nchar = len;
break;
default:
ASN1err(ASN1_F_ASN1_MBSTRING_NCOPY, ASN1_R_UNKNOWN_FORMAT);
return -1;
}
if ((minsize > 0) && (nchar < minsize)) {
ASN1err(ASN1_F_ASN1_MBSTRING_NCOPY, ASN1_R_STRING_TOO_SHORT);
BIO_snprintf(strbuf, sizeof(strbuf), "%ld", minsize);
ERR_add_error_data(2, "minsize=", strbuf);
return -1;
}
if ((maxsize > 0) && (nchar > maxsize)) {
ASN1err(ASN1_F_ASN1_MBSTRING_NCOPY, ASN1_R_STRING_TOO_LONG);
BIO_snprintf(strbuf, sizeof(strbuf), "%ld", maxsize);
ERR_add_error_data(2, "maxsize=", strbuf);
return -1;
}
/* Now work out minimal type (if any) */
if (traverse_string(in, len, inform, type_str, &mask) < 0) {
ASN1err(ASN1_F_ASN1_MBSTRING_NCOPY, ASN1_R_ILLEGAL_CHARACTERS);
return -1;
}
/* Now work out output format and string type */
outform = MBSTRING_ASC;
if (mask & B_ASN1_NUMERICSTRING)
str_type = V_ASN1_NUMERICSTRING;
else if (mask & B_ASN1_PRINTABLESTRING)
str_type = V_ASN1_PRINTABLESTRING;
else if (mask & B_ASN1_IA5STRING)
str_type = V_ASN1_IA5STRING;
else if (mask & B_ASN1_T61STRING)
str_type = V_ASN1_T61STRING;
else if (mask & B_ASN1_BMPSTRING) {
str_type = V_ASN1_BMPSTRING;
outform = MBSTRING_BMP;
} else if (mask & B_ASN1_UNIVERSALSTRING) {
str_type = V_ASN1_UNIVERSALSTRING;
outform = MBSTRING_UNIV;
} else {
str_type = V_ASN1_UTF8STRING;
outform = MBSTRING_UTF8;
}
if (!out)
return str_type;
if (*out) {
free_out = 0;
dest = *out;
OPENSSL_free(dest->data);
dest->data = NULL;
dest->length = 0;
dest->type = str_type;
} else {
free_out = 1;
dest = ASN1_STRING_type_new(str_type);
if (dest == NULL) {
ASN1err(ASN1_F_ASN1_MBSTRING_NCOPY, ERR_R_MALLOC_FAILURE);
return -1;
}
*out = dest;
}
/* If both the same type just copy across */
if (inform == outform) {
if (!ASN1_STRING_set(dest, in, len)) {
ASN1err(ASN1_F_ASN1_MBSTRING_NCOPY, ERR_R_MALLOC_FAILURE);
return -1;
}
return str_type;
}
/* Work out how much space the destination will need */
switch (outform) {
case MBSTRING_ASC:
outlen = nchar;
cpyfunc = cpy_asc;
break;
case MBSTRING_BMP:
outlen = nchar << 1;
cpyfunc = cpy_bmp;
break;
case MBSTRING_UNIV:
outlen = nchar << 2;
cpyfunc = cpy_univ;
break;
case MBSTRING_UTF8:
outlen = 0;
traverse_string(in, len, inform, out_utf8, &outlen);
cpyfunc = cpy_utf8;
break;
}
if ((p = OPENSSL_malloc(outlen + 1)) == NULL) {
if (free_out)
ASN1_STRING_free(dest);
ASN1err(ASN1_F_ASN1_MBSTRING_NCOPY, ERR_R_MALLOC_FAILURE);
return -1;
}
dest->length = outlen;
dest->data = p;
p[outlen] = 0;
traverse_string(in, len, inform, cpyfunc, &p);
return str_type;
}
/*
* This function traverses a string and passes the value of each character to
* an optional function along with a void * argument.
*/
static int traverse_string(const unsigned char *p, int len, int inform,
int (*rfunc) (unsigned long value, void *in),
void *arg)
{
unsigned long value;
int ret;
while (len) {
if (inform == MBSTRING_ASC) {
value = *p++;
len--;
} else if (inform == MBSTRING_BMP) {
value = *p++ << 8;
value |= *p++;
len -= 2;
} else if (inform == MBSTRING_UNIV) {
value = ((unsigned long)*p++) << 24;
value |= ((unsigned long)*p++) << 16;
value |= *p++ << 8;
value |= *p++;
len -= 4;
} else {
ret = UTF8_getc(p, len, &value);
if (ret < 0)
return -1;
len -= ret;
p += ret;
}
if (rfunc) {
ret = rfunc(value, arg);
if (ret <= 0)
return ret;
}
}
return 1;
}
/* Various utility functions for traverse_string */
/* Just count number of characters */
static int in_utf8(unsigned long value, void *arg)
{
int *nchar;
nchar = arg;
(*nchar)++;
return 1;
}
/* Determine size of output as a UTF8 String */
static int out_utf8(unsigned long value, void *arg)
{
int *outlen;
outlen = arg;
*outlen += UTF8_putc(NULL, -1, value);
return 1;
}
/*
* Determine the "type" of a string: check each character against a supplied
* "mask".
*/
static int type_str(unsigned long value, void *arg)
{
unsigned long types = *((unsigned long *)arg);
const int native = value > INT_MAX ? INT_MAX : ossl_fromascii(value);
if ((types & B_ASN1_NUMERICSTRING) && !(ossl_isdigit(native)
|| native == ' '))
types &= ~B_ASN1_NUMERICSTRING;
if ((types & B_ASN1_PRINTABLESTRING) && !ossl_isasn1print(native))
types &= ~B_ASN1_PRINTABLESTRING;
if ((types & B_ASN1_IA5STRING) && !ossl_isascii(native))
types &= ~B_ASN1_IA5STRING;
if ((types & B_ASN1_T61STRING) && (value > 0xff))
types &= ~B_ASN1_T61STRING;
if ((types & B_ASN1_BMPSTRING) && (value > 0xffff))
types &= ~B_ASN1_BMPSTRING;
if (!types)
return -1;
*((unsigned long *)arg) = types;
return 1;
}
/* Copy one byte per character ASCII like strings */
static int cpy_asc(unsigned long value, void *arg)
{
unsigned char **p, *q;
p = arg;
q = *p;
*q = (unsigned char)value;
(*p)++;
return 1;
}
/* Copy two byte per character BMPStrings */
static int cpy_bmp(unsigned long value, void *arg)
{
unsigned char **p, *q;
p = arg;
q = *p;
*q++ = (unsigned char)((value >> 8) & 0xff);
*q = (unsigned char)(value & 0xff);
*p += 2;
return 1;
}
/* Copy four byte per character UniversalStrings */
static int cpy_univ(unsigned long value, void *arg)
{
unsigned char **p, *q;
p = arg;
q = *p;
*q++ = (unsigned char)((value >> 24) & 0xff);
*q++ = (unsigned char)((value >> 16) & 0xff);
*q++ = (unsigned char)((value >> 8) & 0xff);
*q = (unsigned char)(value & 0xff);
*p += 4;
return 1;
}
/* Copy to a UTF8String */
static int cpy_utf8(unsigned long value, void *arg)
{
unsigned char **p;
int ret;
p = arg;
/* We already know there is enough room so pass 0xff as the length */
ret = UTF8_putc(*p, 0xff, value);
*p += ret;
return 1;
}

View file

@ -0,0 +1,383 @@
/*
* Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <stdio.h>
#include <limits.h>
#include "internal/ctype.h"
#include "internal/cryptlib.h"
#include <openssl/buffer.h>
#include <openssl/asn1.h>
#include <openssl/objects.h>
#include <openssl/bn.h>
#include "internal/asn1_int.h"
#include "asn1_locl.h"
int i2d_ASN1_OBJECT(const ASN1_OBJECT *a, unsigned char **pp)
{
unsigned char *p, *allocated = NULL;
int objsize;
if ((a == NULL) || (a->data == NULL))
return 0;
objsize = ASN1_object_size(0, a->length, V_ASN1_OBJECT);
if (pp == NULL || objsize == -1)
return objsize;
if (*pp == NULL) {
if ((p = allocated = OPENSSL_malloc(objsize)) == NULL) {
ASN1err(ASN1_F_I2D_ASN1_OBJECT, ERR_R_MALLOC_FAILURE);
return 0;
}
} else {
p = *pp;
}
ASN1_put_object(&p, 0, a->length, V_ASN1_OBJECT, V_ASN1_UNIVERSAL);
memcpy(p, a->data, a->length);
/*
* If a new buffer was allocated, just return it back.
* If not, return the incremented buffer pointer.
*/
*pp = allocated != NULL ? allocated : p + a->length;
return objsize;
}
int a2d_ASN1_OBJECT(unsigned char *out, int olen, const char *buf, int num)
{
int i, first, len = 0, c, use_bn;
char ftmp[24], *tmp = ftmp;
int tmpsize = sizeof(ftmp);
const char *p;
unsigned long l;
BIGNUM *bl = NULL;
if (num == 0)
return 0;
else if (num == -1)
num = strlen(buf);
p = buf;
c = *(p++);
num--;
if ((c >= '0') && (c <= '2')) {
first = c - '0';
} else {
ASN1err(ASN1_F_A2D_ASN1_OBJECT, ASN1_R_FIRST_NUM_TOO_LARGE);
goto err;
}
if (num <= 0) {
ASN1err(ASN1_F_A2D_ASN1_OBJECT, ASN1_R_MISSING_SECOND_NUMBER);
goto err;
}
c = *(p++);
num--;
for (;;) {
if (num <= 0)
break;
if ((c != '.') && (c != ' ')) {
ASN1err(ASN1_F_A2D_ASN1_OBJECT, ASN1_R_INVALID_SEPARATOR);
goto err;
}
l = 0;
use_bn = 0;
for (;;) {
if (num <= 0)
break;
num--;
c = *(p++);
if ((c == ' ') || (c == '.'))
break;
if (!ossl_isdigit(c)) {
ASN1err(ASN1_F_A2D_ASN1_OBJECT, ASN1_R_INVALID_DIGIT);
goto err;
}
if (!use_bn && l >= ((ULONG_MAX - 80) / 10L)) {
use_bn = 1;
if (bl == NULL)
bl = BN_new();
if (bl == NULL || !BN_set_word(bl, l))
goto err;
}
if (use_bn) {
if (!BN_mul_word(bl, 10L)
|| !BN_add_word(bl, c - '0'))
goto err;
} else
l = l * 10L + (long)(c - '0');
}
if (len == 0) {
if ((first < 2) && (l >= 40)) {
ASN1err(ASN1_F_A2D_ASN1_OBJECT,
ASN1_R_SECOND_NUMBER_TOO_LARGE);
goto err;
}
if (use_bn) {
if (!BN_add_word(bl, first * 40))
goto err;
} else
l += (long)first *40;
}
i = 0;
if (use_bn) {
int blsize;
blsize = BN_num_bits(bl);
blsize = (blsize + 6) / 7;
if (blsize > tmpsize) {
if (tmp != ftmp)
OPENSSL_free(tmp);
tmpsize = blsize + 32;
tmp = OPENSSL_malloc(tmpsize);
if (tmp == NULL)
goto err;
}
while (blsize--) {
BN_ULONG t = BN_div_word(bl, 0x80L);
if (t == (BN_ULONG)-1)
goto err;
tmp[i++] = (unsigned char)t;
}
} else {
for (;;) {
tmp[i++] = (unsigned char)l & 0x7f;
l >>= 7L;
if (l == 0L)
break;
}
}
if (out != NULL) {
if (len + i > olen) {
ASN1err(ASN1_F_A2D_ASN1_OBJECT, ASN1_R_BUFFER_TOO_SMALL);
goto err;
}
while (--i > 0)
out[len++] = tmp[i] | 0x80;
out[len++] = tmp[0];
} else
len += i;
}
if (tmp != ftmp)
OPENSSL_free(tmp);
BN_free(bl);
return len;
err:
if (tmp != ftmp)
OPENSSL_free(tmp);
BN_free(bl);
return 0;
}
int i2t_ASN1_OBJECT(char *buf, int buf_len, const ASN1_OBJECT *a)
{
return OBJ_obj2txt(buf, buf_len, a, 0);
}
int i2a_ASN1_OBJECT(BIO *bp, const ASN1_OBJECT *a)
{
char buf[80], *p = buf;
int i;
if ((a == NULL) || (a->data == NULL))
return BIO_write(bp, "NULL", 4);
i = i2t_ASN1_OBJECT(buf, sizeof(buf), a);
if (i > (int)(sizeof(buf) - 1)) {
if ((p = OPENSSL_malloc(i + 1)) == NULL) {
ASN1err(ASN1_F_I2A_ASN1_OBJECT, ERR_R_MALLOC_FAILURE);
return -1;
}
i2t_ASN1_OBJECT(p, i + 1, a);
}
if (i <= 0) {
i = BIO_write(bp, "<INVALID>", 9);
i += BIO_dump(bp, (const char *)a->data, a->length);
return i;
}
BIO_write(bp, p, i);
if (p != buf)
OPENSSL_free(p);
return i;
}
ASN1_OBJECT *d2i_ASN1_OBJECT(ASN1_OBJECT **a, const unsigned char **pp,
long length)
{
const unsigned char *p;
long len;
int tag, xclass;
int inf, i;
ASN1_OBJECT *ret = NULL;
p = *pp;
inf = ASN1_get_object(&p, &len, &tag, &xclass, length);
if (inf & 0x80) {
i = ASN1_R_BAD_OBJECT_HEADER;
goto err;
}
if (tag != V_ASN1_OBJECT) {
i = ASN1_R_EXPECTING_AN_OBJECT;
goto err;
}
ret = c2i_ASN1_OBJECT(a, &p, len);
if (ret)
*pp = p;
return ret;
err:
ASN1err(ASN1_F_D2I_ASN1_OBJECT, i);
return NULL;
}
ASN1_OBJECT *c2i_ASN1_OBJECT(ASN1_OBJECT **a, const unsigned char **pp,
long len)
{
ASN1_OBJECT *ret = NULL, tobj;
const unsigned char *p;
unsigned char *data;
int i, length;
/*
* Sanity check OID encoding. Need at least one content octet. MSB must
* be clear in the last octet. can't have leading 0x80 in subidentifiers,
* see: X.690 8.19.2
*/
if (len <= 0 || len > INT_MAX || pp == NULL || (p = *pp) == NULL ||
p[len - 1] & 0x80) {
ASN1err(ASN1_F_C2I_ASN1_OBJECT, ASN1_R_INVALID_OBJECT_ENCODING);
return NULL;
}
/* Now 0 < len <= INT_MAX, so the cast is safe. */
length = (int)len;
/*
* Try to lookup OID in table: these are all valid encodings so if we get
* a match we know the OID is valid.
*/
tobj.nid = NID_undef;
tobj.data = p;
tobj.length = length;
tobj.flags = 0;
i = OBJ_obj2nid(&tobj);
if (i != NID_undef) {
/*
* Return shared registered OID object: this improves efficiency
* because we don't have to return a dynamically allocated OID
* and NID lookups can use the cached value.
*/
ret = OBJ_nid2obj(i);
if (a) {
ASN1_OBJECT_free(*a);
*a = ret;
}
*pp += len;
return ret;
}
for (i = 0; i < length; i++, p++) {
if (*p == 0x80 && (!i || !(p[-1] & 0x80))) {
ASN1err(ASN1_F_C2I_ASN1_OBJECT, ASN1_R_INVALID_OBJECT_ENCODING);
return NULL;
}
}
/*
* only the ASN1_OBJECTs from the 'table' will have values for ->sn or
* ->ln
*/
if ((a == NULL) || ((*a) == NULL) ||
!((*a)->flags & ASN1_OBJECT_FLAG_DYNAMIC)) {
if ((ret = ASN1_OBJECT_new()) == NULL)
return NULL;
} else
ret = (*a);
p = *pp;
/* detach data from object */
data = (unsigned char *)ret->data;
ret->data = NULL;
/* once detached we can change it */
if ((data == NULL) || (ret->length < length)) {
ret->length = 0;
OPENSSL_free(data);
data = OPENSSL_malloc(length);
if (data == NULL) {
i = ERR_R_MALLOC_FAILURE;
goto err;
}
ret->flags |= ASN1_OBJECT_FLAG_DYNAMIC_DATA;
}
memcpy(data, p, length);
/* reattach data to object, after which it remains const */
ret->data = data;
ret->length = length;
ret->sn = NULL;
ret->ln = NULL;
/* ret->flags=ASN1_OBJECT_FLAG_DYNAMIC; we know it is dynamic */
p += length;
if (a != NULL)
(*a) = ret;
*pp = p;
return ret;
err:
ASN1err(ASN1_F_C2I_ASN1_OBJECT, i);
if ((a == NULL) || (*a != ret))
ASN1_OBJECT_free(ret);
return NULL;
}
ASN1_OBJECT *ASN1_OBJECT_new(void)
{
ASN1_OBJECT *ret;
ret = OPENSSL_zalloc(sizeof(*ret));
if (ret == NULL) {
ASN1err(ASN1_F_ASN1_OBJECT_NEW, ERR_R_MALLOC_FAILURE);
return NULL;
}
ret->flags = ASN1_OBJECT_FLAG_DYNAMIC;
return ret;
}
void ASN1_OBJECT_free(ASN1_OBJECT *a)
{
if (a == NULL)
return;
if (a->flags & ASN1_OBJECT_FLAG_DYNAMIC_STRINGS) {
#ifndef CONST_STRICT /* disable purely for compile-time strict
* const checking. Doing this on a "real"
* compile will cause memory leaks */
OPENSSL_free((void*)a->sn);
OPENSSL_free((void*)a->ln);
#endif
a->sn = a->ln = NULL;
}
if (a->flags & ASN1_OBJECT_FLAG_DYNAMIC_DATA) {
OPENSSL_free((void*)a->data);
a->data = NULL;
a->length = 0;
}
if (a->flags & ASN1_OBJECT_FLAG_DYNAMIC)
OPENSSL_free(a);
}
ASN1_OBJECT *ASN1_OBJECT_create(int nid, unsigned char *data, int len,
const char *sn, const char *ln)
{
ASN1_OBJECT o;
o.sn = sn;
o.ln = ln;
o.data = data;
o.nid = nid;
o.length = len;
o.flags = ASN1_OBJECT_FLAG_DYNAMIC | ASN1_OBJECT_FLAG_DYNAMIC_STRINGS |
ASN1_OBJECT_FLAG_DYNAMIC_DATA;
return OBJ_dup(&o);
}

View file

@ -0,0 +1,29 @@
/*
* Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <stdio.h>
#include "internal/cryptlib.h"
#include <openssl/asn1.h>
ASN1_OCTET_STRING *ASN1_OCTET_STRING_dup(const ASN1_OCTET_STRING *x)
{
return ASN1_STRING_dup(x);
}
int ASN1_OCTET_STRING_cmp(const ASN1_OCTET_STRING *a,
const ASN1_OCTET_STRING *b)
{
return ASN1_STRING_cmp(a, b);
}
int ASN1_OCTET_STRING_set(ASN1_OCTET_STRING *x, const unsigned char *d,
int len)
{
return ASN1_STRING_set(x, d, len);
}

View file

@ -0,0 +1,95 @@
/*
* Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <stdio.h>
#include "internal/ctype.h"
#include "internal/cryptlib.h"
#include <openssl/asn1.h>
int ASN1_PRINTABLE_type(const unsigned char *s, int len)
{
int c;
int ia5 = 0;
int t61 = 0;
if (len <= 0)
len = -1;
if (s == NULL)
return V_ASN1_PRINTABLESTRING;
while ((*s) && (len-- != 0)) {
c = *(s++);
if (!ossl_isasn1print(c))
ia5 = 1;
if (!ossl_isascii(c))
t61 = 1;
}
if (t61)
return V_ASN1_T61STRING;
if (ia5)
return V_ASN1_IA5STRING;
return V_ASN1_PRINTABLESTRING;
}
int ASN1_UNIVERSALSTRING_to_string(ASN1_UNIVERSALSTRING *s)
{
int i;
unsigned char *p;
if (s->type != V_ASN1_UNIVERSALSTRING)
return 0;
if ((s->length % 4) != 0)
return 0;
p = s->data;
for (i = 0; i < s->length; i += 4) {
if ((p[0] != '\0') || (p[1] != '\0') || (p[2] != '\0'))
break;
else
p += 4;
}
if (i < s->length)
return 0;
p = s->data;
for (i = 3; i < s->length; i += 4) {
*(p++) = s->data[i];
}
*(p) = '\0';
s->length /= 4;
s->type = ASN1_PRINTABLE_type(s->data, s->length);
return 1;
}
int ASN1_STRING_print(BIO *bp, const ASN1_STRING *v)
{
int i, n;
char buf[80];
const char *p;
if (v == NULL)
return 0;
n = 0;
p = (const char *)v->data;
for (i = 0; i < v->length; i++) {
if ((p[i] > '~') || ((p[i] < ' ') &&
(p[i] != '\n') && (p[i] != '\r')))
buf[n] = '.';
else
buf[n] = p[i];
n++;
if (n >= 80) {
if (BIO_write(bp, buf, n) <= 0)
return 0;
n = 0;
}
}
if (n > 0)
if (BIO_write(bp, buf, n) <= 0)
return 0;
return 1;
}

View file

@ -0,0 +1,241 @@
/*
* Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <stdio.h>
#include <time.h>
#include <sys/types.h>
#include "internal/cryptlib.h"
#include <openssl/bn.h>
#include <openssl/evp.h>
#include <openssl/x509.h>
#include <openssl/objects.h>
#include <openssl/buffer.h>
#include "internal/asn1_int.h"
#include "internal/evp_int.h"
#ifndef NO_ASN1_OLD
int ASN1_sign(i2d_of_void *i2d, X509_ALGOR *algor1, X509_ALGOR *algor2,
ASN1_BIT_STRING *signature, char *data, EVP_PKEY *pkey,
const EVP_MD *type)
{
EVP_MD_CTX *ctx = EVP_MD_CTX_new();
unsigned char *p, *buf_in = NULL, *buf_out = NULL;
int i, inl = 0, outl = 0;
size_t inll = 0, outll = 0;
X509_ALGOR *a;
if (ctx == NULL) {
ASN1err(ASN1_F_ASN1_SIGN, ERR_R_MALLOC_FAILURE);
goto err;
}
for (i = 0; i < 2; i++) {
if (i == 0)
a = algor1;
else
a = algor2;
if (a == NULL)
continue;
if (type->pkey_type == NID_dsaWithSHA1) {
/*
* special case: RFC 2459 tells us to omit 'parameters' with
* id-dsa-with-sha1
*/
ASN1_TYPE_free(a->parameter);
a->parameter = NULL;
} else if ((a->parameter == NULL) ||
(a->parameter->type != V_ASN1_NULL)) {
ASN1_TYPE_free(a->parameter);
if ((a->parameter = ASN1_TYPE_new()) == NULL)
goto err;
a->parameter->type = V_ASN1_NULL;
}
ASN1_OBJECT_free(a->algorithm);
a->algorithm = OBJ_nid2obj(type->pkey_type);
if (a->algorithm == NULL) {
ASN1err(ASN1_F_ASN1_SIGN, ASN1_R_UNKNOWN_OBJECT_TYPE);
goto err;
}
if (a->algorithm->length == 0) {
ASN1err(ASN1_F_ASN1_SIGN,
ASN1_R_THE_ASN1_OBJECT_IDENTIFIER_IS_NOT_KNOWN_FOR_THIS_MD);
goto err;
}
}
inl = i2d(data, NULL);
if (inl <= 0) {
ASN1err(ASN1_F_ASN1_SIGN, ERR_R_INTERNAL_ERROR);
goto err;
}
inll = (size_t)inl;
buf_in = OPENSSL_malloc(inll);
outll = outl = EVP_PKEY_size(pkey);
buf_out = OPENSSL_malloc(outll);
if (buf_in == NULL || buf_out == NULL) {
outl = 0;
ASN1err(ASN1_F_ASN1_SIGN, ERR_R_MALLOC_FAILURE);
goto err;
}
p = buf_in;
i2d(data, &p);
if (!EVP_SignInit_ex(ctx, type, NULL)
|| !EVP_SignUpdate(ctx, (unsigned char *)buf_in, inl)
|| !EVP_SignFinal(ctx, (unsigned char *)buf_out,
(unsigned int *)&outl, pkey)) {
outl = 0;
ASN1err(ASN1_F_ASN1_SIGN, ERR_R_EVP_LIB);
goto err;
}
OPENSSL_free(signature->data);
signature->data = buf_out;
buf_out = NULL;
signature->length = outl;
/*
* In the interests of compatibility, I'll make sure that the bit string
* has a 'not-used bits' value of 0
*/
signature->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07);
signature->flags |= ASN1_STRING_FLAG_BITS_LEFT;
err:
EVP_MD_CTX_free(ctx);
OPENSSL_clear_free((char *)buf_in, inll);
OPENSSL_clear_free((char *)buf_out, outll);
return outl;
}
#endif
int ASN1_item_sign(const ASN1_ITEM *it, X509_ALGOR *algor1,
X509_ALGOR *algor2, ASN1_BIT_STRING *signature, void *asn,
EVP_PKEY *pkey, const EVP_MD *type)
{
int rv;
EVP_MD_CTX *ctx = EVP_MD_CTX_new();
if (ctx == NULL) {
ASN1err(ASN1_F_ASN1_ITEM_SIGN, ERR_R_MALLOC_FAILURE);
return 0;
}
if (!EVP_DigestSignInit(ctx, NULL, type, NULL, pkey)) {
EVP_MD_CTX_free(ctx);
return 0;
}
rv = ASN1_item_sign_ctx(it, algor1, algor2, signature, asn, ctx);
EVP_MD_CTX_free(ctx);
return rv;
}
int ASN1_item_sign_ctx(const ASN1_ITEM *it,
X509_ALGOR *algor1, X509_ALGOR *algor2,
ASN1_BIT_STRING *signature, void *asn, EVP_MD_CTX *ctx)
{
const EVP_MD *type;
EVP_PKEY *pkey;
unsigned char *buf_in = NULL, *buf_out = NULL;
size_t inl = 0, outl = 0, outll = 0;
int signid, paramtype, buf_len = 0;
int rv;
type = EVP_MD_CTX_md(ctx);
pkey = EVP_PKEY_CTX_get0_pkey(EVP_MD_CTX_pkey_ctx(ctx));
if (pkey == NULL) {
ASN1err(ASN1_F_ASN1_ITEM_SIGN_CTX, ASN1_R_CONTEXT_NOT_INITIALISED);
goto err;
}
if (pkey->ameth == NULL) {
ASN1err(ASN1_F_ASN1_ITEM_SIGN_CTX, ASN1_R_DIGEST_AND_KEY_TYPE_NOT_SUPPORTED);
goto err;
}
if (pkey->ameth->item_sign) {
rv = pkey->ameth->item_sign(ctx, it, asn, algor1, algor2, signature);
if (rv == 1)
outl = signature->length;
/*-
* Return value meanings:
* <=0: error.
* 1: method does everything.
* 2: carry on as normal.
* 3: ASN1 method sets algorithm identifiers: just sign.
*/
if (rv <= 0)
ASN1err(ASN1_F_ASN1_ITEM_SIGN_CTX, ERR_R_EVP_LIB);
if (rv <= 1)
goto err;
} else {
rv = 2;
}
if (rv == 2) {
if (type == NULL) {
ASN1err(ASN1_F_ASN1_ITEM_SIGN_CTX, ASN1_R_CONTEXT_NOT_INITIALISED);
goto err;
}
if (!OBJ_find_sigid_by_algs(&signid,
EVP_MD_nid(type),
pkey->ameth->pkey_id)) {
ASN1err(ASN1_F_ASN1_ITEM_SIGN_CTX,
ASN1_R_DIGEST_AND_KEY_TYPE_NOT_SUPPORTED);
goto err;
}
if (pkey->ameth->pkey_flags & ASN1_PKEY_SIGPARAM_NULL)
paramtype = V_ASN1_NULL;
else
paramtype = V_ASN1_UNDEF;
if (algor1)
X509_ALGOR_set0(algor1, OBJ_nid2obj(signid), paramtype, NULL);
if (algor2)
X509_ALGOR_set0(algor2, OBJ_nid2obj(signid), paramtype, NULL);
}
buf_len = ASN1_item_i2d(asn, &buf_in, it);
if (buf_len <= 0) {
outl = 0;
ASN1err(ASN1_F_ASN1_ITEM_SIGN_CTX, ERR_R_INTERNAL_ERROR);
goto err;
}
inl = buf_len;
outll = outl = EVP_PKEY_size(pkey);
buf_out = OPENSSL_malloc(outll);
if (buf_in == NULL || buf_out == NULL) {
outl = 0;
ASN1err(ASN1_F_ASN1_ITEM_SIGN_CTX, ERR_R_MALLOC_FAILURE);
goto err;
}
if (!EVP_DigestSign(ctx, buf_out, &outl, buf_in, inl)) {
outl = 0;
ASN1err(ASN1_F_ASN1_ITEM_SIGN_CTX, ERR_R_EVP_LIB);
goto err;
}
OPENSSL_free(signature->data);
signature->data = buf_out;
buf_out = NULL;
signature->length = outl;
/*
* In the interests of compatibility, I'll make sure that the bit string
* has a 'not-used bits' value of 0
*/
signature->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07);
signature->flags |= ASN1_STRING_FLAG_BITS_LEFT;
err:
OPENSSL_clear_free((char *)buf_in, inl);
OPENSSL_clear_free((char *)buf_out, outll);
return outl;
}

View file

@ -0,0 +1,626 @@
/*
* Copyright 2000-2018 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <stdio.h>
#include <string.h>
#include "internal/cryptlib.h"
#include "internal/asn1_int.h"
#include <openssl/crypto.h>
#include <openssl/x509.h>
#include <openssl/asn1.h>
#include "charmap.h"
/*
* ASN1_STRING_print_ex() and X509_NAME_print_ex(). Enhanced string and name
* printing routines handling multibyte characters, RFC2253 and a host of
* other options.
*/
#define CHARTYPE_BS_ESC (ASN1_STRFLGS_ESC_2253 | CHARTYPE_FIRST_ESC_2253 | CHARTYPE_LAST_ESC_2253)
#define ESC_FLAGS (ASN1_STRFLGS_ESC_2253 | \
ASN1_STRFLGS_ESC_2254 | \
ASN1_STRFLGS_ESC_QUOTE | \
ASN1_STRFLGS_ESC_CTRL | \
ASN1_STRFLGS_ESC_MSB)
/*
* Three IO functions for sending data to memory, a BIO and and a FILE
* pointer.
*/
static int send_bio_chars(void *arg, const void *buf, int len)
{
if (!arg)
return 1;
if (BIO_write(arg, buf, len) != len)
return 0;
return 1;
}
#ifndef OPENSSL_NO_STDIO
static int send_fp_chars(void *arg, const void *buf, int len)
{
if (!arg)
return 1;
if (fwrite(buf, 1, len, arg) != (unsigned int)len)
return 0;
return 1;
}
#endif
typedef int char_io (void *arg, const void *buf, int len);
/*
* This function handles display of strings, one character at a time. It is
* passed an unsigned long for each character because it could come from 2 or
* even 4 byte forms.
*/
static int do_esc_char(unsigned long c, unsigned short flags, char *do_quotes,
char_io *io_ch, void *arg)
{
unsigned short chflgs;
unsigned char chtmp;
char tmphex[HEX_SIZE(long) + 3];
if (c > 0xffffffffL)
return -1;
if (c > 0xffff) {
BIO_snprintf(tmphex, sizeof(tmphex), "\\W%08lX", c);
if (!io_ch(arg, tmphex, 10))
return -1;
return 10;
}
if (c > 0xff) {
BIO_snprintf(tmphex, sizeof(tmphex), "\\U%04lX", c);
if (!io_ch(arg, tmphex, 6))
return -1;
return 6;
}
chtmp = (unsigned char)c;
if (chtmp > 0x7f)
chflgs = flags & ASN1_STRFLGS_ESC_MSB;
else
chflgs = char_type[chtmp] & flags;
if (chflgs & CHARTYPE_BS_ESC) {
/* If we don't escape with quotes, signal we need quotes */
if (chflgs & ASN1_STRFLGS_ESC_QUOTE) {
if (do_quotes)
*do_quotes = 1;
if (!io_ch(arg, &chtmp, 1))
return -1;
return 1;
}
if (!io_ch(arg, "\\", 1))
return -1;
if (!io_ch(arg, &chtmp, 1))
return -1;
return 2;
}
if (chflgs & (ASN1_STRFLGS_ESC_CTRL
| ASN1_STRFLGS_ESC_MSB
| ASN1_STRFLGS_ESC_2254)) {
BIO_snprintf(tmphex, 11, "\\%02X", chtmp);
if (!io_ch(arg, tmphex, 3))
return -1;
return 3;
}
/*
* If we get this far and do any escaping at all must escape the escape
* character itself: backslash.
*/
if (chtmp == '\\' && (flags & ESC_FLAGS)) {
if (!io_ch(arg, "\\\\", 2))
return -1;
return 2;
}
if (!io_ch(arg, &chtmp, 1))
return -1;
return 1;
}
#define BUF_TYPE_WIDTH_MASK 0x7
#define BUF_TYPE_CONVUTF8 0x8
/*
* This function sends each character in a buffer to do_esc_char(). It
* interprets the content formats and converts to or from UTF8 as
* appropriate.
*/
static int do_buf(unsigned char *buf, int buflen,
int type, unsigned short flags, char *quotes, char_io *io_ch,
void *arg)
{
int i, outlen, len, charwidth;
unsigned short orflags;
unsigned char *p, *q;
unsigned long c;
p = buf;
q = buf + buflen;
outlen = 0;
charwidth = type & BUF_TYPE_WIDTH_MASK;
switch (charwidth) {
case 4:
if (buflen & 3) {
ASN1err(ASN1_F_DO_BUF, ASN1_R_INVALID_UNIVERSALSTRING_LENGTH);
return -1;
}
break;
case 2:
if (buflen & 1) {
ASN1err(ASN1_F_DO_BUF, ASN1_R_INVALID_BMPSTRING_LENGTH);
return -1;
}
break;
default:
break;
}
while (p != q) {
if (p == buf && flags & ASN1_STRFLGS_ESC_2253)
orflags = CHARTYPE_FIRST_ESC_2253;
else
orflags = 0;
switch (charwidth) {
case 4:
c = ((unsigned long)*p++) << 24;
c |= ((unsigned long)*p++) << 16;
c |= ((unsigned long)*p++) << 8;
c |= *p++;
break;
case 2:
c = ((unsigned long)*p++) << 8;
c |= *p++;
break;
case 1:
c = *p++;
break;
case 0:
i = UTF8_getc(p, buflen, &c);
if (i < 0)
return -1; /* Invalid UTF8String */
buflen -= i;
p += i;
break;
default:
return -1; /* invalid width */
}
if (p == q && flags & ASN1_STRFLGS_ESC_2253)
orflags = CHARTYPE_LAST_ESC_2253;
if (type & BUF_TYPE_CONVUTF8) {
unsigned char utfbuf[6];
int utflen;
utflen = UTF8_putc(utfbuf, sizeof(utfbuf), c);
for (i = 0; i < utflen; i++) {
/*
* We don't need to worry about setting orflags correctly
* because if utflen==1 its value will be correct anyway
* otherwise each character will be > 0x7f and so the
* character will never be escaped on first and last.
*/
len = do_esc_char(utfbuf[i], flags | orflags, quotes,
io_ch, arg);
if (len < 0)
return -1;
outlen += len;
}
} else {
len = do_esc_char(c, flags | orflags, quotes,
io_ch, arg);
if (len < 0)
return -1;
outlen += len;
}
}
return outlen;
}
/* This function hex dumps a buffer of characters */
static int do_hex_dump(char_io *io_ch, void *arg, unsigned char *buf,
int buflen)
{
static const char hexdig[] = "0123456789ABCDEF";
unsigned char *p, *q;
char hextmp[2];
if (arg) {
p = buf;
q = buf + buflen;
while (p != q) {
hextmp[0] = hexdig[*p >> 4];
hextmp[1] = hexdig[*p & 0xf];
if (!io_ch(arg, hextmp, 2))
return -1;
p++;
}
}
return buflen << 1;
}
/*
* "dump" a string. This is done when the type is unknown, or the flags
* request it. We can either dump the content octets or the entire DER
* encoding. This uses the RFC2253 #01234 format.
*/
static int do_dump(unsigned long lflags, char_io *io_ch, void *arg,
const ASN1_STRING *str)
{
/*
* Placing the ASN1_STRING in a temp ASN1_TYPE allows the DER encoding to
* readily obtained
*/
ASN1_TYPE t;
unsigned char *der_buf, *p;
int outlen, der_len;
if (!io_ch(arg, "#", 1))
return -1;
/* If we don't dump DER encoding just dump content octets */
if (!(lflags & ASN1_STRFLGS_DUMP_DER)) {
outlen = do_hex_dump(io_ch, arg, str->data, str->length);
if (outlen < 0)
return -1;
return outlen + 1;
}
t.type = str->type;
t.value.ptr = (char *)str;
der_len = i2d_ASN1_TYPE(&t, NULL);
if ((der_buf = OPENSSL_malloc(der_len)) == NULL) {
ASN1err(ASN1_F_DO_DUMP, ERR_R_MALLOC_FAILURE);
return -1;
}
p = der_buf;
i2d_ASN1_TYPE(&t, &p);
outlen = do_hex_dump(io_ch, arg, der_buf, der_len);
OPENSSL_free(der_buf);
if (outlen < 0)
return -1;
return outlen + 1;
}
/*
* Lookup table to convert tags to character widths, 0 = UTF8 encoded, -1 is
* used for non string types otherwise it is the number of bytes per
* character
*/
static const signed char tag2nbyte[] = {
-1, -1, -1, -1, -1, /* 0-4 */
-1, -1, -1, -1, -1, /* 5-9 */
-1, -1, /* 10-11 */
0, /* 12 V_ASN1_UTF8STRING */
-1, -1, -1, -1, -1, /* 13-17 */
1, /* 18 V_ASN1_NUMERICSTRING */
1, /* 19 V_ASN1_PRINTABLESTRING */
1, /* 20 V_ASN1_T61STRING */
-1, /* 21 */
1, /* 22 V_ASN1_IA5STRING */
1, /* 23 V_ASN1_UTCTIME */
1, /* 24 V_ASN1_GENERALIZEDTIME */
-1, /* 25 */
1, /* 26 V_ASN1_ISO64STRING */
-1, /* 27 */
4, /* 28 V_ASN1_UNIVERSALSTRING */
-1, /* 29 */
2 /* 30 V_ASN1_BMPSTRING */
};
/*
* This is the main function, print out an ASN1_STRING taking note of various
* escape and display options. Returns number of characters written or -1 if
* an error occurred.
*/
static int do_print_ex(char_io *io_ch, void *arg, unsigned long lflags,
const ASN1_STRING *str)
{
int outlen, len;
int type;
char quotes;
unsigned short flags;
quotes = 0;
/* Keep a copy of escape flags */
flags = (unsigned short)(lflags & ESC_FLAGS);
type = str->type;
outlen = 0;
if (lflags & ASN1_STRFLGS_SHOW_TYPE) {
const char *tagname;
tagname = ASN1_tag2str(type);
outlen += strlen(tagname);
if (!io_ch(arg, tagname, outlen) || !io_ch(arg, ":", 1))
return -1;
outlen++;
}
/* Decide what to do with type, either dump content or display it */
/* Dump everything */
if (lflags & ASN1_STRFLGS_DUMP_ALL)
type = -1;
/* Ignore the string type */
else if (lflags & ASN1_STRFLGS_IGNORE_TYPE)
type = 1;
else {
/* Else determine width based on type */
if ((type > 0) && (type < 31))
type = tag2nbyte[type];
else
type = -1;
if ((type == -1) && !(lflags & ASN1_STRFLGS_DUMP_UNKNOWN))
type = 1;
}
if (type == -1) {
len = do_dump(lflags, io_ch, arg, str);
if (len < 0)
return -1;
outlen += len;
return outlen;
}
if (lflags & ASN1_STRFLGS_UTF8_CONVERT) {
/*
* Note: if string is UTF8 and we want to convert to UTF8 then we
* just interpret it as 1 byte per character to avoid converting
* twice.
*/
if (!type)
type = 1;
else
type |= BUF_TYPE_CONVUTF8;
}
len = do_buf(str->data, str->length, type, flags, &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, const X509_NAME *n,
int indent, unsigned long flags)
{
int i, prev = -1, orflags, cnt;
int fn_opt, fn_nid;
ASN1_OBJECT *fn;
const ASN1_STRING *val;
const X509_NAME_ENTRY *ent;
char objtmp[80];
const char *objbuf;
int outlen, len;
char *sep_dn, *sep_mv, *sep_eq;
int sep_dn_len, sep_mv_len, sep_eq_len;
if (indent < 0)
indent = 0;
outlen = indent;
if (!do_indent(io_ch, arg, indent))
return -1;
switch (flags & XN_FLAG_SEP_MASK) {
case XN_FLAG_SEP_MULTILINE:
sep_dn = "\n";
sep_dn_len = 1;
sep_mv = " + ";
sep_mv_len = 3;
break;
case XN_FLAG_SEP_COMMA_PLUS:
sep_dn = ",";
sep_dn_len = 1;
sep_mv = "+";
sep_mv_len = 1;
indent = 0;
break;
case XN_FLAG_SEP_CPLUS_SPC:
sep_dn = ", ";
sep_dn_len = 2;
sep_mv = " + ";
sep_mv_len = 3;
indent = 0;
break;
case XN_FLAG_SEP_SPLUS_SPC:
sep_dn = "; ";
sep_dn_len = 2;
sep_mv = " + ";
sep_mv_len = 3;
indent = 0;
break;
default:
return -1;
}
if (flags & XN_FLAG_SPC_EQ) {
sep_eq = " = ";
sep_eq_len = 3;
} else {
sep_eq = "=";
sep_eq_len = 1;
}
fn_opt = flags & XN_FLAG_FN_MASK;
cnt = X509_NAME_entry_count(n);
for (i = 0; i < cnt; i++) {
if (flags & XN_FLAG_DN_REV)
ent = X509_NAME_get_entry(n, cnt - i - 1);
else
ent = X509_NAME_get_entry(n, i);
if (prev != -1) {
if (prev == X509_NAME_ENTRY_set(ent)) {
if (!io_ch(arg, sep_mv, sep_mv_len))
return -1;
outlen += sep_mv_len;
} else {
if (!io_ch(arg, sep_dn, sep_dn_len))
return -1;
outlen += sep_dn_len;
if (!do_indent(io_ch, arg, indent))
return -1;
outlen += indent;
}
}
prev = X509_NAME_ENTRY_set(ent);
fn = X509_NAME_ENTRY_get_object(ent);
val = X509_NAME_ENTRY_get_data(ent);
fn_nid = OBJ_obj2nid(fn);
if (fn_opt != XN_FLAG_FN_NONE) {
int objlen, fld_len;
if ((fn_opt == XN_FLAG_FN_OID) || (fn_nid == NID_undef)) {
OBJ_obj2txt(objtmp, sizeof(objtmp), fn, 1);
fld_len = 0; /* XXX: what should this be? */
objbuf = objtmp;
} else {
if (fn_opt == XN_FLAG_FN_SN) {
fld_len = FN_WIDTH_SN;
objbuf = OBJ_nid2sn(fn_nid);
} else if (fn_opt == XN_FLAG_FN_LN) {
fld_len = FN_WIDTH_LN;
objbuf = OBJ_nid2ln(fn_nid);
} else {
fld_len = 0; /* XXX: what should this be? */
objbuf = "";
}
}
objlen = strlen(objbuf);
if (!io_ch(arg, objbuf, objlen))
return -1;
if ((objlen < fld_len) && (flags & XN_FLAG_FN_ALIGN)) {
if (!do_indent(io_ch, arg, fld_len - objlen))
return -1;
outlen += fld_len - objlen;
}
if (!io_ch(arg, sep_eq, sep_eq_len))
return -1;
outlen += objlen + sep_eq_len;
}
/*
* If the field name is unknown then fix up the DER dump flag. We
* might want to limit this further so it will DER dump on anything
* other than a few 'standard' fields.
*/
if ((fn_nid == NID_undef) && (flags & XN_FLAG_DUMP_UNKNOWN_FIELDS))
orflags = ASN1_STRFLGS_DUMP_ALL;
else
orflags = 0;
len = do_print_ex(io_ch, arg, flags | orflags, val);
if (len < 0)
return -1;
outlen += len;
}
return outlen;
}
/* Wrappers round the main functions */
int X509_NAME_print_ex(BIO *out, const X509_NAME *nm, int indent,
unsigned long flags)
{
if (flags == XN_FLAG_COMPAT)
return X509_NAME_print(out, nm, indent);
return do_name_ex(send_bio_chars, out, nm, indent, flags);
}
#ifndef OPENSSL_NO_STDIO
int X509_NAME_print_ex_fp(FILE *fp, const X509_NAME *nm, int indent,
unsigned long flags)
{
if (flags == XN_FLAG_COMPAT) {
BIO *btmp;
int ret;
btmp = BIO_new_fp(fp, BIO_NOCLOSE);
if (!btmp)
return -1;
ret = X509_NAME_print(btmp, nm, indent);
BIO_free(btmp);
return ret;
}
return do_name_ex(send_fp_chars, fp, nm, indent, flags);
}
#endif
int ASN1_STRING_print_ex(BIO *out, const ASN1_STRING *str, unsigned long flags)
{
return do_print_ex(send_bio_chars, out, flags, str);
}
#ifndef OPENSSL_NO_STDIO
int ASN1_STRING_print_ex_fp(FILE *fp, const ASN1_STRING *str, unsigned long flags)
{
return do_print_ex(send_fp_chars, fp, flags, str);
}
#endif
/*
* Utility function: convert any string type to UTF8, returns number of bytes
* in output string or a negative error code
*/
int ASN1_STRING_to_UTF8(unsigned char **out, const ASN1_STRING *in)
{
ASN1_STRING stmp, *str = &stmp;
int mbflag, type, ret;
if (!in)
return -1;
type = in->type;
if ((type < 0) || (type > 30))
return -1;
mbflag = tag2nbyte[type];
if (mbflag == -1)
return -1;
mbflag |= MBSTRING_FLAG;
stmp.data = NULL;
stmp.length = 0;
stmp.flags = 0;
ret =
ASN1_mbstring_copy(&str, in->data, in->length, mbflag,
B_ASN1_UTF8STRING);
if (ret < 0)
return ret;
*out = stmp.data;
return stmp.length;
}

View file

@ -0,0 +1,219 @@
/*
* Copyright 1999-2018 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <stdio.h>
#include "internal/cryptlib.h"
#include <openssl/asn1.h>
#include <openssl/objects.h>
static STACK_OF(ASN1_STRING_TABLE) *stable = NULL;
static void st_free(ASN1_STRING_TABLE *tbl);
static int sk_table_cmp(const ASN1_STRING_TABLE *const *a,
const ASN1_STRING_TABLE *const *b);
/*
* This is the global mask for the mbstring functions: this is use to mask
* out certain types (such as BMPString and UTF8String) because certain
* software (e.g. Netscape) has problems with them.
*/
static unsigned long global_mask = B_ASN1_UTF8STRING;
void ASN1_STRING_set_default_mask(unsigned long mask)
{
global_mask = mask;
}
unsigned long ASN1_STRING_get_default_mask(void)
{
return global_mask;
}
/*-
* This function sets the default to various "flavours" of configuration.
* based on an ASCII string. Currently this is:
* MASK:XXXX : a numerical mask value.
* nobmp : Don't use BMPStrings (just Printable, T61).
* pkix : PKIX recommendation in RFC2459.
* utf8only : only use UTF8Strings (RFC2459 recommendation for 2004).
* default: the default value, Printable, T61, BMP.
*/
int ASN1_STRING_set_default_mask_asc(const char *p)
{
unsigned long mask;
char *end;
if (strncmp(p, "MASK:", 5) == 0) {
if (!p[5])
return 0;
mask = strtoul(p + 5, &end, 0);
if (*end)
return 0;
} else if (strcmp(p, "nombstr") == 0)
mask = ~((unsigned long)(B_ASN1_BMPSTRING | B_ASN1_UTF8STRING));
else if (strcmp(p, "pkix") == 0)
mask = ~((unsigned long)B_ASN1_T61STRING);
else if (strcmp(p, "utf8only") == 0)
mask = B_ASN1_UTF8STRING;
else if (strcmp(p, "default") == 0)
mask = 0xFFFFFFFFL;
else
return 0;
ASN1_STRING_set_default_mask(mask);
return 1;
}
/*
* The following function generates an ASN1_STRING based on limits in a
* table. Frequently the types and length of an ASN1_STRING are restricted by
* a corresponding OID. For example certificates and certificate requests.
*/
ASN1_STRING *ASN1_STRING_set_by_NID(ASN1_STRING **out,
const unsigned char *in, int inlen,
int inform, int nid)
{
ASN1_STRING_TABLE *tbl;
ASN1_STRING *str = NULL;
unsigned long mask;
int ret;
if (out == NULL)
out = &str;
tbl = ASN1_STRING_TABLE_get(nid);
if (tbl != NULL) {
mask = tbl->mask;
if (!(tbl->flags & STABLE_NO_MASK))
mask &= global_mask;
ret = ASN1_mbstring_ncopy(out, in, inlen, inform, mask,
tbl->minsize, tbl->maxsize);
} else {
ret = ASN1_mbstring_copy(out, in, inlen, inform,
DIRSTRING_TYPE & global_mask);
}
if (ret <= 0)
return NULL;
return *out;
}
/*
* Now the tables and helper functions for the string table:
*/
#include "tbl_standard.h"
static int sk_table_cmp(const ASN1_STRING_TABLE *const *a,
const ASN1_STRING_TABLE *const *b)
{
return (*a)->nid - (*b)->nid;
}
DECLARE_OBJ_BSEARCH_CMP_FN(ASN1_STRING_TABLE, ASN1_STRING_TABLE, table);
static int table_cmp(const ASN1_STRING_TABLE *a, const ASN1_STRING_TABLE *b)
{
return a->nid - b->nid;
}
IMPLEMENT_OBJ_BSEARCH_CMP_FN(ASN1_STRING_TABLE, ASN1_STRING_TABLE, table);
ASN1_STRING_TABLE *ASN1_STRING_TABLE_get(int nid)
{
int idx;
ASN1_STRING_TABLE fnd;
fnd.nid = nid;
if (stable) {
idx = sk_ASN1_STRING_TABLE_find(stable, &fnd);
if (idx >= 0)
return sk_ASN1_STRING_TABLE_value(stable, idx);
}
return OBJ_bsearch_table(&fnd, tbl_standard, OSSL_NELEM(tbl_standard));
}
/*
* Return a string table pointer which can be modified: either directly from
* table or a copy of an internal value added to the table.
*/
static ASN1_STRING_TABLE *stable_get(int nid)
{
ASN1_STRING_TABLE *tmp, *rv;
/* Always need a string table so allocate one if NULL */
if (stable == NULL) {
stable = sk_ASN1_STRING_TABLE_new(sk_table_cmp);
if (stable == NULL)
return NULL;
}
tmp = ASN1_STRING_TABLE_get(nid);
if (tmp != NULL && tmp->flags & STABLE_FLAGS_MALLOC)
return tmp;
if ((rv = OPENSSL_zalloc(sizeof(*rv))) == NULL) {
ASN1err(ASN1_F_STABLE_GET, ERR_R_MALLOC_FAILURE);
return NULL;
}
if (!sk_ASN1_STRING_TABLE_push(stable, rv)) {
OPENSSL_free(rv);
return NULL;
}
if (tmp != NULL) {
rv->nid = tmp->nid;
rv->minsize = tmp->minsize;
rv->maxsize = tmp->maxsize;
rv->mask = tmp->mask;
rv->flags = tmp->flags | STABLE_FLAGS_MALLOC;
} else {
rv->nid = nid;
rv->minsize = -1;
rv->maxsize = -1;
rv->flags = STABLE_FLAGS_MALLOC;
}
return rv;
}
int ASN1_STRING_TABLE_add(int nid,
long minsize, long maxsize, unsigned long mask,
unsigned long flags)
{
ASN1_STRING_TABLE *tmp;
tmp = stable_get(nid);
if (tmp == NULL) {
ASN1err(ASN1_F_ASN1_STRING_TABLE_ADD, ERR_R_MALLOC_FAILURE);
return 0;
}
if (minsize >= 0)
tmp->minsize = minsize;
if (maxsize >= 0)
tmp->maxsize = maxsize;
if (mask)
tmp->mask = mask;
if (flags)
tmp->flags = STABLE_FLAGS_MALLOC | flags;
return 1;
}
void ASN1_STRING_TABLE_cleanup(void)
{
STACK_OF(ASN1_STRING_TABLE) *tmp;
tmp = stable;
if (tmp == NULL)
return;
stable = NULL;
sk_ASN1_STRING_TABLE_pop_free(tmp, st_free);
}
static void st_free(ASN1_STRING_TABLE *tbl)
{
if (tbl->flags & STABLE_FLAGS_MALLOC)
OPENSSL_free(tbl);
}

View file

@ -0,0 +1,553 @@
/*
* Copyright 1999-2017 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
/*-
* This is an implementation of the ASN1 Time structure which is:
* Time ::= CHOICE {
* utcTime UTCTime,
* generalTime GeneralizedTime }
*/
#include <stdio.h>
#include <time.h>
#include "internal/ctype.h"
#include "internal/cryptlib.h"
#include <openssl/asn1t.h>
#include "asn1_locl.h"
IMPLEMENT_ASN1_MSTRING(ASN1_TIME, B_ASN1_TIME)
IMPLEMENT_ASN1_FUNCTIONS(ASN1_TIME)
static int is_utc(const int year)
{
if (50 <= year && year <= 149)
return 1;
return 0;
}
static int leap_year(const int year)
{
if (year % 400 == 0 || (year % 100 != 0 && year % 4 == 0))
return 1;
return 0;
}
/*
* Compute the day of the week and the day of the year from the year, month
* and day. The day of the year is straightforward, the day of the week uses
* a form of Zeller's congruence. For this months start with March and are
* numbered 4 through 15.
*/
static void determine_days(struct tm *tm)
{
static const int ydays[12] = {
0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334
};
int y = tm->tm_year + 1900;
int m = tm->tm_mon;
int d = tm->tm_mday;
int c;
tm->tm_yday = ydays[m] + d - 1;
if (m >= 2) {
/* March and onwards can be one day further into the year */
tm->tm_yday += leap_year(y);
m += 2;
} else {
/* Treat January and February as part of the previous year */
m += 14;
y--;
}
c = y / 100;
y %= 100;
/* Zeller's congruance */
tm->tm_wday = (d + (13 * m) / 5 + y + y / 4 + c / 4 + 5 * c + 6) % 7;
}
int asn1_time_to_tm(struct tm *tm, const ASN1_TIME *d)
{
static const int min[9] = { 0, 0, 1, 1, 0, 0, 0, 0, 0 };
static const int max[9] = { 99, 99, 12, 31, 23, 59, 59, 12, 59 };
static const int mdays[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
char *a;
int n, i, i2, l, o, min_l = 11, strict = 0, end = 6, btz = 5, md;
struct tm tmp;
/*
* ASN1_STRING_FLAG_X509_TIME is used to enforce RFC 5280
* time string format, in which:
*
* 1. "seconds" is a 'MUST'
* 2. "Zulu" timezone is a 'MUST'
* 3. "+|-" is not allowed to indicate a time zone
*/
if (d->type == V_ASN1_UTCTIME) {
if (d->flags & ASN1_STRING_FLAG_X509_TIME) {
min_l = 13;
strict = 1;
}
} else if (d->type == V_ASN1_GENERALIZEDTIME) {
end = 7;
btz = 6;
if (d->flags & ASN1_STRING_FLAG_X509_TIME) {
min_l = 15;
strict = 1;
} else {
min_l = 13;
}
} else {
return 0;
}
l = d->length;
a = (char *)d->data;
o = 0;
memset(&tmp, 0, sizeof(tmp));
/*
* GENERALIZEDTIME is similar to UTCTIME except the year is represented
* as YYYY. This stuff treats everything as a two digit field so make
* first two fields 00 to 99
*/
if (l < min_l)
goto err;
for (i = 0; i < end; i++) {
if (!strict && (i == btz) && ((a[o] == 'Z') || (a[o] == '+') || (a[o] == '-'))) {
i++;
break;
}
if (!ossl_isdigit(a[o]))
goto err;
n = a[o] - '0';
/* incomplete 2-digital number */
if (++o == l)
goto err;
if (!ossl_isdigit(a[o]))
goto err;
n = (n * 10) + a[o] - '0';
/* no more bytes to read, but we haven't seen time-zone yet */
if (++o == l)
goto err;
i2 = (d->type == V_ASN1_UTCTIME) ? i + 1 : i;
if ((n < min[i2]) || (n > max[i2]))
goto err;
switch (i2) {
case 0:
/* UTC will never be here */
tmp.tm_year = n * 100 - 1900;
break;
case 1:
if (d->type == V_ASN1_UTCTIME)
tmp.tm_year = n < 50 ? n + 100 : n;
else
tmp.tm_year += n;
break;
case 2:
tmp.tm_mon = n - 1;
break;
case 3:
/* check if tm_mday is valid in tm_mon */
if (tmp.tm_mon == 1) {
/* it's February */
md = mdays[1] + leap_year(tmp.tm_year + 1900);
} else {
md = mdays[tmp.tm_mon];
}
if (n > md)
goto err;
tmp.tm_mday = n;
determine_days(&tmp);
break;
case 4:
tmp.tm_hour = n;
break;
case 5:
tmp.tm_min = n;
break;
case 6:
tmp.tm_sec = n;
break;
}
}
/*
* Optional fractional seconds: decimal point followed by one or more
* digits.
*/
if (d->type == V_ASN1_GENERALIZEDTIME && a[o] == '.') {
if (strict)
/* RFC 5280 forbids fractional seconds */
goto err;
if (++o == l)
goto err;
i = o;
while ((o < l) && ossl_isdigit(a[o]))
o++;
/* Must have at least one digit after decimal point */
if (i == o)
goto err;
/* no more bytes to read, but we haven't seen time-zone yet */
if (o == l)
goto err;
}
/*
* 'o' will never point to '\0' at this point, the only chance
* 'o' can point to '\0' is either the subsequent if or the first
* else if is true.
*/
if (a[o] == 'Z') {
o++;
} else if (!strict && ((a[o] == '+') || (a[o] == '-'))) {
int offsign = a[o] == '-' ? 1 : -1;
int offset = 0;
o++;
/*
* if not equal, no need to do subsequent checks
* since the following for-loop will add 'o' by 4
* and the final return statement will check if 'l'
* and 'o' are equal.
*/
if (o + 4 != l)
goto err;
for (i = end; i < end + 2; i++) {
if (!ossl_isdigit(a[o]))
goto err;
n = a[o] - '0';
o++;
if (!ossl_isdigit(a[o]))
goto err;
n = (n * 10) + a[o] - '0';
i2 = (d->type == V_ASN1_UTCTIME) ? i + 1 : i;
if ((n < min[i2]) || (n > max[i2]))
goto err;
/* if tm is NULL, no need to adjust */
if (tm != NULL) {
if (i == end)
offset = n * 3600;
else if (i == end + 1)
offset += n * 60;
}
o++;
}
if (offset && !OPENSSL_gmtime_adj(&tmp, 0, offset * offsign))
goto err;
} else {
/* not Z, or not +/- in non-strict mode */
goto err;
}
if (o == l) {
/* success, check if tm should be filled */
if (tm != NULL)
*tm = tmp;
return 1;
}
err:
return 0;
}
ASN1_TIME *asn1_time_from_tm(ASN1_TIME *s, struct tm *ts, int type)
{
char* p;
ASN1_TIME *tmps = NULL;
const size_t len = 20;
if (type == V_ASN1_UNDEF) {
if (is_utc(ts->tm_year))
type = V_ASN1_UTCTIME;
else
type = V_ASN1_GENERALIZEDTIME;
} else if (type == V_ASN1_UTCTIME) {
if (!is_utc(ts->tm_year))
goto err;
} else if (type != V_ASN1_GENERALIZEDTIME) {
goto err;
}
if (s == NULL)
tmps = ASN1_STRING_new();
else
tmps = s;
if (tmps == NULL)
return NULL;
if (!ASN1_STRING_set(tmps, NULL, len))
goto err;
tmps->type = type;
p = (char*)tmps->data;
if (type == V_ASN1_GENERALIZEDTIME)
tmps->length = BIO_snprintf(p, len, "%04d%02d%02d%02d%02d%02dZ",
ts->tm_year + 1900, ts->tm_mon + 1,
ts->tm_mday, ts->tm_hour, ts->tm_min,
ts->tm_sec);
else
tmps->length = BIO_snprintf(p, len, "%02d%02d%02d%02d%02d%02dZ",
ts->tm_year % 100, ts->tm_mon + 1,
ts->tm_mday, ts->tm_hour, ts->tm_min,
ts->tm_sec);
#ifdef CHARSET_EBCDIC_not
ebcdic2ascii(tmps->data, tmps->data, tmps->length);
#endif
return tmps;
err:
if (tmps != s)
ASN1_STRING_free(tmps);
return NULL;
}
ASN1_TIME *ASN1_TIME_set(ASN1_TIME *s, time_t t)
{
return ASN1_TIME_adj(s, t, 0, 0);
}
ASN1_TIME *ASN1_TIME_adj(ASN1_TIME *s, time_t t,
int offset_day, long offset_sec)
{
struct tm *ts;
struct tm data;
ts = OPENSSL_gmtime(&t, &data);
if (ts == NULL) {
ASN1err(ASN1_F_ASN1_TIME_ADJ, ASN1_R_ERROR_GETTING_TIME);
return NULL;
}
if (offset_day || offset_sec) {
if (!OPENSSL_gmtime_adj(ts, offset_day, offset_sec))
return NULL;
}
return asn1_time_from_tm(s, ts, V_ASN1_UNDEF);
}
int ASN1_TIME_check(const ASN1_TIME *t)
{
if (t->type == V_ASN1_GENERALIZEDTIME)
return ASN1_GENERALIZEDTIME_check(t);
else if (t->type == V_ASN1_UTCTIME)
return ASN1_UTCTIME_check(t);
return 0;
}
/* Convert an ASN1_TIME structure to GeneralizedTime */
ASN1_GENERALIZEDTIME *ASN1_TIME_to_generalizedtime(const ASN1_TIME *t,
ASN1_GENERALIZEDTIME **out)
{
ASN1_GENERALIZEDTIME *ret = NULL;
struct tm tm;
if (!ASN1_TIME_to_tm(t, &tm))
return NULL;
if (out != NULL)
ret = *out;
ret = asn1_time_from_tm(ret, &tm, V_ASN1_GENERALIZEDTIME);
if (out != NULL && ret != NULL)
*out = ret;
return ret;
}
int ASN1_TIME_set_string(ASN1_TIME *s, const char *str)
{
/* Try UTC, if that fails, try GENERALIZED */
if (ASN1_UTCTIME_set_string(s, str))
return 1;
return ASN1_GENERALIZEDTIME_set_string(s, str);
}
int ASN1_TIME_set_string_X509(ASN1_TIME *s, const char *str)
{
ASN1_TIME t;
struct tm tm;
int rv = 0;
t.length = strlen(str);
t.data = (unsigned char *)str;
t.flags = ASN1_STRING_FLAG_X509_TIME;
t.type = V_ASN1_UTCTIME;
if (!ASN1_TIME_check(&t)) {
t.type = V_ASN1_GENERALIZEDTIME;
if (!ASN1_TIME_check(&t))
goto out;
}
/*
* Per RFC 5280 (section 4.1.2.5.), the valid input time
* strings should be encoded with the following rules:
*
* 1. UTC: YYMMDDHHMMSSZ, if YY < 50 (20YY) --> UTC: YYMMDDHHMMSSZ
* 2. UTC: YYMMDDHHMMSSZ, if YY >= 50 (19YY) --> UTC: YYMMDDHHMMSSZ
* 3. G'd: YYYYMMDDHHMMSSZ, if YYYY >= 2050 --> G'd: YYYYMMDDHHMMSSZ
* 4. G'd: YYYYMMDDHHMMSSZ, if YYYY < 2050 --> UTC: YYMMDDHHMMSSZ
*
* Only strings of the 4th rule should be reformatted, but since a
* UTC can only present [1950, 2050), so if the given time string
* is less than 1950 (e.g. 19230419000000Z), we do nothing...
*/
if (s != NULL && t.type == V_ASN1_GENERALIZEDTIME) {
if (!asn1_time_to_tm(&tm, &t))
goto out;
if (is_utc(tm.tm_year)) {
t.length -= 2;
/*
* it's OK to let original t.data go since that's assigned
* to a piece of memory allocated outside of this function.
* new t.data would be freed after ASN1_STRING_copy is done.
*/
t.data = OPENSSL_zalloc(t.length + 1);
if (t.data == NULL)
goto out;
memcpy(t.data, str + 2, t.length);
t.type = V_ASN1_UTCTIME;
}
}
if (s == NULL || ASN1_STRING_copy((ASN1_STRING *)s, (ASN1_STRING *)&t))
rv = 1;
if (t.data != (unsigned char *)str)
OPENSSL_free(t.data);
out:
return rv;
}
int ASN1_TIME_to_tm(const ASN1_TIME *s, struct tm *tm)
{
if (s == NULL) {
time_t now_t;
time(&now_t);
memset(tm, 0, sizeof(*tm));
if (OPENSSL_gmtime(&now_t, tm) != NULL)
return 1;
return 0;
}
return asn1_time_to_tm(tm, s);
}
int ASN1_TIME_diff(int *pday, int *psec,
const ASN1_TIME *from, const ASN1_TIME *to)
{
struct tm tm_from, tm_to;
if (!ASN1_TIME_to_tm(from, &tm_from))
return 0;
if (!ASN1_TIME_to_tm(to, &tm_to))
return 0;
return OPENSSL_gmtime_diff(pday, psec, &tm_from, &tm_to);
}
static const char _asn1_mon[12][4] = {
"Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
};
int ASN1_TIME_print(BIO *bp, const ASN1_TIME *tm)
{
char *v;
int gmt = 0, l;
struct tm stm;
if (!asn1_time_to_tm(&stm, tm)) {
/* asn1_time_to_tm will check the time type */
goto err;
}
l = tm->length;
v = (char *)tm->data;
if (v[l - 1] == 'Z')
gmt = 1;
if (tm->type == V_ASN1_GENERALIZEDTIME) {
char *f = NULL;
int f_len = 0;
/*
* Try to parse fractional seconds. '14' is the place of
* 'fraction point' in a GeneralizedTime string.
*/
if (tm->length > 15 && v[14] == '.') {
f = &v[14];
f_len = 1;
while (14 + f_len < l && ossl_isdigit(f[f_len]))
++f_len;
}
return BIO_printf(bp, "%s %2d %02d:%02d:%02d%.*s %d%s",
_asn1_mon[stm.tm_mon], stm.tm_mday, stm.tm_hour,
stm.tm_min, stm.tm_sec, f_len, f, stm.tm_year + 1900,
(gmt ? " GMT" : "")) > 0;
} else {
return BIO_printf(bp, "%s %2d %02d:%02d:%02d %d%s",
_asn1_mon[stm.tm_mon], stm.tm_mday, stm.tm_hour,
stm.tm_min, stm.tm_sec, stm.tm_year + 1900,
(gmt ? " GMT" : "")) > 0;
}
err:
BIO_write(bp, "Bad time value", 14);
return 0;
}
int ASN1_TIME_cmp_time_t(const ASN1_TIME *s, time_t t)
{
struct tm stm, ttm;
int day, sec;
if (!ASN1_TIME_to_tm(s, &stm))
return -2;
if (!OPENSSL_gmtime(&t, &ttm))
return -2;
if (!OPENSSL_gmtime_diff(&day, &sec, &ttm, &stm))
return -2;
if (day > 0 || sec > 0)
return 1;
if (day < 0 || sec < 0)
return -1;
return 0;
}
int ASN1_TIME_normalize(ASN1_TIME *t)
{
struct tm tm;
if (!ASN1_TIME_to_tm(t, &tm))
return 0;
return asn1_time_from_tm(t, &tm, V_ASN1_UNDEF) != NULL;
}
int ASN1_TIME_compare(const ASN1_TIME *a, const ASN1_TIME *b)
{
int day, sec;
if (!ASN1_TIME_diff(&day, &sec, b, a))
return -2;
if (day > 0 || sec > 0)
return 1;
if (day < 0 || sec < 0)
return -1;
return 0;
}

View file

@ -0,0 +1,134 @@
/*
* Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <stdio.h>
#include "internal/cryptlib.h"
#include <openssl/asn1t.h>
#include <openssl/objects.h>
#include "asn1_locl.h"
int ASN1_TYPE_get(const ASN1_TYPE *a)
{
if ((a->value.ptr != NULL) || (a->type == V_ASN1_NULL))
return a->type;
else
return 0;
}
void ASN1_TYPE_set(ASN1_TYPE *a, int type, void *value)
{
if (a->value.ptr != NULL) {
ASN1_TYPE **tmp_a = &a;
asn1_primitive_free((ASN1_VALUE **)tmp_a, NULL, 0);
}
a->type = type;
if (type == V_ASN1_BOOLEAN)
a->value.boolean = value ? 0xff : 0;
else
a->value.ptr = value;
}
int ASN1_TYPE_set1(ASN1_TYPE *a, int type, const void *value)
{
if (!value || (type == V_ASN1_BOOLEAN)) {
void *p = (void *)value;
ASN1_TYPE_set(a, type, p);
} else if (type == V_ASN1_OBJECT) {
ASN1_OBJECT *odup;
odup = OBJ_dup(value);
if (!odup)
return 0;
ASN1_TYPE_set(a, type, odup);
} else {
ASN1_STRING *sdup;
sdup = ASN1_STRING_dup(value);
if (!sdup)
return 0;
ASN1_TYPE_set(a, type, sdup);
}
return 1;
}
/* Returns 0 if they are equal, != 0 otherwise. */
int ASN1_TYPE_cmp(const ASN1_TYPE *a, const ASN1_TYPE *b)
{
int result = -1;
if (!a || !b || a->type != b->type)
return -1;
switch (a->type) {
case V_ASN1_OBJECT:
result = OBJ_cmp(a->value.object, b->value.object);
break;
case V_ASN1_BOOLEAN:
result = a->value.boolean - b->value.boolean;
break;
case V_ASN1_NULL:
result = 0; /* They do not have content. */
break;
case V_ASN1_INTEGER:
case V_ASN1_ENUMERATED:
case V_ASN1_BIT_STRING:
case V_ASN1_OCTET_STRING:
case V_ASN1_SEQUENCE:
case V_ASN1_SET:
case V_ASN1_NUMERICSTRING:
case V_ASN1_PRINTABLESTRING:
case V_ASN1_T61STRING:
case V_ASN1_VIDEOTEXSTRING:
case V_ASN1_IA5STRING:
case V_ASN1_UTCTIME:
case V_ASN1_GENERALIZEDTIME:
case V_ASN1_GRAPHICSTRING:
case V_ASN1_VISIBLESTRING:
case V_ASN1_GENERALSTRING:
case V_ASN1_UNIVERSALSTRING:
case V_ASN1_BMPSTRING:
case V_ASN1_UTF8STRING:
case V_ASN1_OTHER:
default:
result = ASN1_STRING_cmp((ASN1_STRING *)a->value.ptr,
(ASN1_STRING *)b->value.ptr);
break;
}
return result;
}
ASN1_TYPE *ASN1_TYPE_pack_sequence(const ASN1_ITEM *it, void *s, ASN1_TYPE **t)
{
ASN1_OCTET_STRING *oct;
ASN1_TYPE *rt;
oct = ASN1_item_pack(s, it, NULL);
if (oct == NULL)
return NULL;
if (t && *t) {
rt = *t;
} else {
rt = ASN1_TYPE_new();
if (rt == NULL) {
ASN1_OCTET_STRING_free(oct);
return NULL;
}
if (t)
*t = rt;
}
ASN1_TYPE_set(rt, V_ASN1_SEQUENCE, oct);
return rt;
}
void *ASN1_TYPE_unpack_sequence(const ASN1_ITEM *it, const ASN1_TYPE *t)
{
if (t == NULL || t->type != V_ASN1_SEQUENCE || t->value.sequence == NULL)
return NULL;
return ASN1_item_unpack(t->value.sequence, it);
}

View file

@ -0,0 +1,98 @@
/*
* Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <stdio.h>
#include <time.h>
#include "internal/cryptlib.h"
#include <openssl/asn1.h>
#include "asn1_locl.h"
/* This is the primary function used to parse ASN1_UTCTIME */
int asn1_utctime_to_tm(struct tm *tm, const ASN1_UTCTIME *d)
{
/* wrapper around ans1_time_to_tm */
if (d->type != V_ASN1_UTCTIME)
return 0;
return asn1_time_to_tm(tm, d);
}
int ASN1_UTCTIME_check(const ASN1_UTCTIME *d)
{
return asn1_utctime_to_tm(NULL, d);
}
/* Sets the string via simple copy without cleaning it up */
int ASN1_UTCTIME_set_string(ASN1_UTCTIME *s, const char *str)
{
ASN1_UTCTIME t;
t.type = V_ASN1_UTCTIME;
t.length = strlen(str);
t.data = (unsigned char *)str;
t.flags = 0;
if (!ASN1_UTCTIME_check(&t))
return 0;
if (s != NULL && !ASN1_STRING_copy(s, &t))
return 0;
return 1;
}
ASN1_UTCTIME *ASN1_UTCTIME_set(ASN1_UTCTIME *s, time_t t)
{
return ASN1_UTCTIME_adj(s, t, 0, 0);
}
ASN1_UTCTIME *ASN1_UTCTIME_adj(ASN1_UTCTIME *s, time_t t,
int offset_day, long offset_sec)
{
struct tm *ts;
struct tm data;
ts = OPENSSL_gmtime(&t, &data);
if (ts == NULL)
return NULL;
if (offset_day || offset_sec) {
if (!OPENSSL_gmtime_adj(ts, offset_day, offset_sec))
return NULL;
}
return asn1_time_from_tm(s, ts, V_ASN1_UTCTIME);
}
int ASN1_UTCTIME_cmp_time_t(const ASN1_UTCTIME *s, time_t t)
{
struct tm stm, ttm;
int day, sec;
if (!asn1_utctime_to_tm(&stm, s))
return -2;
if (OPENSSL_gmtime(&t, &ttm) == NULL)
return -2;
if (!OPENSSL_gmtime_diff(&day, &sec, &ttm, &stm))
return -2;
if (day > 0 || sec > 0)
return 1;
if (day < 0 || sec < 0)
return -1;
return 0;
}
int ASN1_UTCTIME_print(BIO *bp, const ASN1_UTCTIME *tm)
{
if (tm->type != V_ASN1_UTCTIME)
return 0;
return ASN1_TIME_print(bp, tm);
}

View file

@ -0,0 +1,188 @@
/*
* Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <stdio.h>
#include "internal/cryptlib.h"
#include <openssl/asn1.h>
/* UTF8 utilities */
/*-
* This parses a UTF8 string one character at a time. It is passed a pointer
* to the string and the length of the string. It sets 'value' to the value of
* the current character. It returns the number of characters read or a
* negative error code:
* -1 = string too short
* -2 = illegal character
* -3 = subsequent characters not of the form 10xxxxxx
* -4 = character encoded incorrectly (not minimal length).
*/
int UTF8_getc(const unsigned char *str, int len, unsigned long *val)
{
const unsigned char *p;
unsigned long value;
int ret;
if (len <= 0)
return 0;
p = str;
/* Check syntax and work out the encoded value (if correct) */
if ((*p & 0x80) == 0) {
value = *p++ & 0x7f;
ret = 1;
} else if ((*p & 0xe0) == 0xc0) {
if (len < 2)
return -1;
if ((p[1] & 0xc0) != 0x80)
return -3;
value = (*p++ & 0x1f) << 6;
value |= *p++ & 0x3f;
if (value < 0x80)
return -4;
ret = 2;
} else if ((*p & 0xf0) == 0xe0) {
if (len < 3)
return -1;
if (((p[1] & 0xc0) != 0x80)
|| ((p[2] & 0xc0) != 0x80))
return -3;
value = (*p++ & 0xf) << 12;
value |= (*p++ & 0x3f) << 6;
value |= *p++ & 0x3f;
if (value < 0x800)
return -4;
ret = 3;
} else if ((*p & 0xf8) == 0xf0) {
if (len < 4)
return -1;
if (((p[1] & 0xc0) != 0x80)
|| ((p[2] & 0xc0) != 0x80)
|| ((p[3] & 0xc0) != 0x80))
return -3;
value = ((unsigned long)(*p++ & 0x7)) << 18;
value |= (*p++ & 0x3f) << 12;
value |= (*p++ & 0x3f) << 6;
value |= *p++ & 0x3f;
if (value < 0x10000)
return -4;
ret = 4;
} else if ((*p & 0xfc) == 0xf8) {
if (len < 5)
return -1;
if (((p[1] & 0xc0) != 0x80)
|| ((p[2] & 0xc0) != 0x80)
|| ((p[3] & 0xc0) != 0x80)
|| ((p[4] & 0xc0) != 0x80))
return -3;
value = ((unsigned long)(*p++ & 0x3)) << 24;
value |= ((unsigned long)(*p++ & 0x3f)) << 18;
value |= ((unsigned long)(*p++ & 0x3f)) << 12;
value |= (*p++ & 0x3f) << 6;
value |= *p++ & 0x3f;
if (value < 0x200000)
return -4;
ret = 5;
} else if ((*p & 0xfe) == 0xfc) {
if (len < 6)
return -1;
if (((p[1] & 0xc0) != 0x80)
|| ((p[2] & 0xc0) != 0x80)
|| ((p[3] & 0xc0) != 0x80)
|| ((p[4] & 0xc0) != 0x80)
|| ((p[5] & 0xc0) != 0x80))
return -3;
value = ((unsigned long)(*p++ & 0x1)) << 30;
value |= ((unsigned long)(*p++ & 0x3f)) << 24;
value |= ((unsigned long)(*p++ & 0x3f)) << 18;
value |= ((unsigned long)(*p++ & 0x3f)) << 12;
value |= (*p++ & 0x3f) << 6;
value |= *p++ & 0x3f;
if (value < 0x4000000)
return -4;
ret = 6;
} else
return -2;
*val = value;
return ret;
}
/*
* This takes a character 'value' and writes the UTF8 encoded value in 'str'
* where 'str' is a buffer containing 'len' characters. Returns the number of
* characters written or -1 if 'len' is too small. 'str' can be set to NULL
* in which case it just returns the number of characters. It will need at
* most 6 characters.
*/
int UTF8_putc(unsigned char *str, int len, unsigned long value)
{
if (!str)
len = 6; /* Maximum we will need */
else if (len <= 0)
return -1;
if (value < 0x80) {
if (str)
*str = (unsigned char)value;
return 1;
}
if (value < 0x800) {
if (len < 2)
return -1;
if (str) {
*str++ = (unsigned char)(((value >> 6) & 0x1f) | 0xc0);
*str = (unsigned char)((value & 0x3f) | 0x80);
}
return 2;
}
if (value < 0x10000) {
if (len < 3)
return -1;
if (str) {
*str++ = (unsigned char)(((value >> 12) & 0xf) | 0xe0);
*str++ = (unsigned char)(((value >> 6) & 0x3f) | 0x80);
*str = (unsigned char)((value & 0x3f) | 0x80);
}
return 3;
}
if (value < 0x200000) {
if (len < 4)
return -1;
if (str) {
*str++ = (unsigned char)(((value >> 18) & 0x7) | 0xf0);
*str++ = (unsigned char)(((value >> 12) & 0x3f) | 0x80);
*str++ = (unsigned char)(((value >> 6) & 0x3f) | 0x80);
*str = (unsigned char)((value & 0x3f) | 0x80);
}
return 4;
}
if (value < 0x4000000) {
if (len < 5)
return -1;
if (str) {
*str++ = (unsigned char)(((value >> 24) & 0x3) | 0xf8);
*str++ = (unsigned char)(((value >> 18) & 0x3f) | 0x80);
*str++ = (unsigned char)(((value >> 12) & 0x3f) | 0x80);
*str++ = (unsigned char)(((value >> 6) & 0x3f) | 0x80);
*str = (unsigned char)((value & 0x3f) | 0x80);
}
return 5;
}
if (len < 6)
return -1;
if (str) {
*str++ = (unsigned char)(((value >> 30) & 0x1) | 0xfc);
*str++ = (unsigned char)(((value >> 24) & 0x3f) | 0x80);
*str++ = (unsigned char)(((value >> 18) & 0x3f) | 0x80);
*str++ = (unsigned char)(((value >> 12) & 0x3f) | 0x80);
*str++ = (unsigned char)(((value >> 6) & 0x3f) | 0x80);
*str = (unsigned char)((value & 0x3f) | 0x80);
}
return 6;
}

View file

@ -0,0 +1,178 @@
/*
* Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <stdio.h>
#include <time.h>
#include <sys/types.h>
#include "internal/cryptlib.h"
#include <openssl/bn.h>
#include <openssl/x509.h>
#include <openssl/objects.h>
#include <openssl/buffer.h>
#include <openssl/evp.h>
#include "internal/asn1_int.h"
#include "internal/evp_int.h"
#ifndef NO_ASN1_OLD
int ASN1_verify(i2d_of_void *i2d, X509_ALGOR *a, ASN1_BIT_STRING *signature,
char *data, EVP_PKEY *pkey)
{
EVP_MD_CTX *ctx = EVP_MD_CTX_new();
const EVP_MD *type;
unsigned char *p, *buf_in = NULL;
int ret = -1, i, inl;
if (ctx == NULL) {
ASN1err(ASN1_F_ASN1_VERIFY, ERR_R_MALLOC_FAILURE);
goto err;
}
i = OBJ_obj2nid(a->algorithm);
type = EVP_get_digestbyname(OBJ_nid2sn(i));
if (type == NULL) {
ASN1err(ASN1_F_ASN1_VERIFY, ASN1_R_UNKNOWN_MESSAGE_DIGEST_ALGORITHM);
goto err;
}
if (signature->type == V_ASN1_BIT_STRING && signature->flags & 0x7) {
ASN1err(ASN1_F_ASN1_VERIFY, ASN1_R_INVALID_BIT_STRING_BITS_LEFT);
goto err;
}
inl = i2d(data, NULL);
if (inl <= 0) {
ASN1err(ASN1_F_ASN1_VERIFY, ERR_R_INTERNAL_ERROR);
goto err;
}
buf_in = OPENSSL_malloc((unsigned int)inl);
if (buf_in == NULL) {
ASN1err(ASN1_F_ASN1_VERIFY, ERR_R_MALLOC_FAILURE);
goto err;
}
p = buf_in;
i2d(data, &p);
ret = EVP_VerifyInit_ex(ctx, type, NULL)
&& EVP_VerifyUpdate(ctx, (unsigned char *)buf_in, inl);
OPENSSL_clear_free(buf_in, (unsigned int)inl);
if (!ret) {
ASN1err(ASN1_F_ASN1_VERIFY, ERR_R_EVP_LIB);
goto err;
}
ret = -1;
if (EVP_VerifyFinal(ctx, (unsigned char *)signature->data,
(unsigned int)signature->length, pkey) <= 0) {
ASN1err(ASN1_F_ASN1_VERIFY, ERR_R_EVP_LIB);
ret = 0;
goto err;
}
ret = 1;
err:
EVP_MD_CTX_free(ctx);
return ret;
}
#endif
int ASN1_item_verify(const ASN1_ITEM *it, X509_ALGOR *a,
ASN1_BIT_STRING *signature, void *asn, EVP_PKEY *pkey)
{
EVP_MD_CTX *ctx = NULL;
unsigned char *buf_in = NULL;
int ret = -1, inl = 0;
int mdnid, pknid;
size_t inll = 0;
if (!pkey) {
ASN1err(ASN1_F_ASN1_ITEM_VERIFY, ERR_R_PASSED_NULL_PARAMETER);
return -1;
}
if (signature->type == V_ASN1_BIT_STRING && signature->flags & 0x7) {
ASN1err(ASN1_F_ASN1_ITEM_VERIFY, ASN1_R_INVALID_BIT_STRING_BITS_LEFT);
return -1;
}
ctx = EVP_MD_CTX_new();
if (ctx == NULL) {
ASN1err(ASN1_F_ASN1_ITEM_VERIFY, ERR_R_MALLOC_FAILURE);
goto err;
}
/* Convert signature OID into digest and public key OIDs */
if (!OBJ_find_sigid_algs(OBJ_obj2nid(a->algorithm), &mdnid, &pknid)) {
ASN1err(ASN1_F_ASN1_ITEM_VERIFY, ASN1_R_UNKNOWN_SIGNATURE_ALGORITHM);
goto err;
}
if (mdnid == NID_undef) {
if (!pkey->ameth || !pkey->ameth->item_verify) {
ASN1err(ASN1_F_ASN1_ITEM_VERIFY,
ASN1_R_UNKNOWN_SIGNATURE_ALGORITHM);
goto err;
}
ret = pkey->ameth->item_verify(ctx, it, asn, a, signature, pkey);
/*
* Return value of 2 means carry on, anything else means we exit
* straight away: either a fatal error of the underlying verification
* routine handles all verification.
*/
if (ret != 2)
goto err;
ret = -1;
} else {
const EVP_MD *type = 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 (inl <= 0) {
ASN1err(ASN1_F_ASN1_ITEM_VERIFY, ERR_R_INTERNAL_ERROR);
goto err;
}
if (buf_in == NULL) {
ASN1err(ASN1_F_ASN1_ITEM_VERIFY, ERR_R_MALLOC_FAILURE);
goto err;
}
inll = inl;
ret = EVP_DigestVerify(ctx, signature->data, (size_t)signature->length,
buf_in, inl);
if (ret <= 0) {
ASN1err(ASN1_F_ASN1_ITEM_VERIFY, ERR_R_EVP_LIB);
goto err;
}
ret = 1;
err:
OPENSSL_clear_free(buf_in, inll);
EVP_MD_CTX_free(ctx);
return ret;
}

View file

@ -0,0 +1,451 @@
/*
* Copyright 2006-2018 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include "e_os.h" /* for strncasecmp */
#include "internal/cryptlib.h"
#include <stdio.h>
#include <openssl/asn1t.h>
#include <openssl/x509.h>
#include <openssl/engine.h>
#include "internal/asn1_int.h"
#include "internal/evp_int.h"
#include "standard_methods.h"
typedef int sk_cmp_fn_type(const char *const *a, const char *const *b);
static STACK_OF(EVP_PKEY_ASN1_METHOD) *app_methods = NULL;
DECLARE_OBJ_BSEARCH_CMP_FN(const EVP_PKEY_ASN1_METHOD *,
const EVP_PKEY_ASN1_METHOD *, ameth);
static int ameth_cmp(const EVP_PKEY_ASN1_METHOD *const *a,
const EVP_PKEY_ASN1_METHOD *const *b)
{
return ((*a)->pkey_id - (*b)->pkey_id);
}
IMPLEMENT_OBJ_BSEARCH_CMP_FN(const EVP_PKEY_ASN1_METHOD *,
const EVP_PKEY_ASN1_METHOD *, ameth);
int EVP_PKEY_asn1_get_count(void)
{
int num = OSSL_NELEM(standard_methods);
if (app_methods)
num += sk_EVP_PKEY_ASN1_METHOD_num(app_methods);
return num;
}
const EVP_PKEY_ASN1_METHOD *EVP_PKEY_asn1_get0(int idx)
{
int num = OSSL_NELEM(standard_methods);
if (idx < 0)
return NULL;
if (idx < num)
return standard_methods[idx];
idx -= num;
return sk_EVP_PKEY_ASN1_METHOD_value(app_methods, idx);
}
static const EVP_PKEY_ASN1_METHOD *pkey_asn1_find(int type)
{
EVP_PKEY_ASN1_METHOD tmp;
const EVP_PKEY_ASN1_METHOD *t = &tmp, **ret;
tmp.pkey_id = type;
if (app_methods) {
int idx;
idx = sk_EVP_PKEY_ASN1_METHOD_find(app_methods, &tmp);
if (idx >= 0)
return sk_EVP_PKEY_ASN1_METHOD_value(app_methods, idx);
}
ret = OBJ_bsearch_ameth(&t, standard_methods, OSSL_NELEM(standard_methods));
if (!ret || !*ret)
return NULL;
return *ret;
}
/*
* Find an implementation of an ASN1 algorithm. If 'pe' is not NULL also
* search through engines and set *pe to a functional reference to the engine
* implementing 'type' or NULL if no engine implements it.
*/
const EVP_PKEY_ASN1_METHOD *EVP_PKEY_asn1_find(ENGINE **pe, int type)
{
const EVP_PKEY_ASN1_METHOD *t;
for (;;) {
t = pkey_asn1_find(type);
if (!t || !(t->pkey_flags & ASN1_PKEY_ALIAS))
break;
type = t->pkey_base_id;
}
if (pe) {
#ifndef OPENSSL_NO_ENGINE
ENGINE *e;
/* type will contain the final unaliased type */
e = ENGINE_get_pkey_asn1_meth_engine(type);
if (e) {
*pe = e;
return ENGINE_get_pkey_asn1_meth(e, type);
}
#endif
*pe = NULL;
}
return t;
}
const EVP_PKEY_ASN1_METHOD *EVP_PKEY_asn1_find_str(ENGINE **pe,
const char *str, int len)
{
int i;
const EVP_PKEY_ASN1_METHOD *ameth = NULL;
if (len == -1)
len = strlen(str);
if (pe) {
#ifndef OPENSSL_NO_ENGINE
ENGINE *e;
ameth = ENGINE_pkey_asn1_find_str(&e, str, len);
if (ameth) {
/*
* Convert structural into functional reference
*/
if (!ENGINE_init(e))
ameth = NULL;
ENGINE_free(e);
*pe = e;
return ameth;
}
#endif
*pe = NULL;
}
for (i = EVP_PKEY_asn1_get_count(); i-- > 0; ) {
ameth = EVP_PKEY_asn1_get0(i);
if (ameth->pkey_flags & ASN1_PKEY_ALIAS)
continue;
if ((int)strlen(ameth->pem_str) == len
&& strncasecmp(ameth->pem_str, str, len) == 0)
return ameth;
}
return NULL;
}
int EVP_PKEY_asn1_add0(const EVP_PKEY_ASN1_METHOD *ameth)
{
EVP_PKEY_ASN1_METHOD tmp = { 0, };
/*
* 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))) {
EVPerr(EVP_F_EVP_PKEY_ASN1_ADD0, ERR_R_PASSED_INVALID_ARGUMENT);
return 0;
}
if (app_methods == NULL) {
app_methods = sk_EVP_PKEY_ASN1_METHOD_new(ameth_cmp);
if (app_methods == NULL)
return 0;
}
tmp.pkey_id = ameth->pkey_id;
if (sk_EVP_PKEY_ASN1_METHOD_find(app_methods, &tmp) >= 0) {
EVPerr(EVP_F_EVP_PKEY_ASN1_ADD0,
EVP_R_PKEY_APPLICATION_ASN1_METHOD_ALREADY_REGISTERED);
return 0;
}
if (!sk_EVP_PKEY_ASN1_METHOD_push(app_methods, ameth))
return 0;
sk_EVP_PKEY_ASN1_METHOD_sort(app_methods);
return 1;
}
int EVP_PKEY_asn1_add_alias(int to, int from)
{
EVP_PKEY_ASN1_METHOD *ameth;
ameth = EVP_PKEY_asn1_new(from, ASN1_PKEY_ALIAS, NULL, NULL);
if (ameth == NULL)
return 0;
ameth->pkey_base_id = to;
if (!EVP_PKEY_asn1_add0(ameth)) {
EVP_PKEY_asn1_free(ameth);
return 0;
}
return 1;
}
int EVP_PKEY_asn1_get0_info(int *ppkey_id, int *ppkey_base_id,
int *ppkey_flags, const char **pinfo,
const char **ppem_str,
const EVP_PKEY_ASN1_METHOD *ameth)
{
if (!ameth)
return 0;
if (ppkey_id)
*ppkey_id = ameth->pkey_id;
if (ppkey_base_id)
*ppkey_base_id = ameth->pkey_base_id;
if (ppkey_flags)
*ppkey_flags = ameth->pkey_flags;
if (pinfo)
*pinfo = ameth->info;
if (ppem_str)
*ppem_str = ameth->pem_str;
return 1;
}
const EVP_PKEY_ASN1_METHOD *EVP_PKEY_get0_asn1(const EVP_PKEY *pkey)
{
return pkey->ameth;
}
EVP_PKEY_ASN1_METHOD *EVP_PKEY_asn1_new(int id, int flags,
const char *pem_str, const char *info)
{
EVP_PKEY_ASN1_METHOD *ameth = OPENSSL_zalloc(sizeof(*ameth));
if (ameth == NULL)
return NULL;
ameth->pkey_id = id;
ameth->pkey_base_id = id;
ameth->pkey_flags = flags | ASN1_PKEY_DYNAMIC;
if (info) {
ameth->info = OPENSSL_strdup(info);
if (!ameth->info)
goto err;
}
if (pem_str) {
ameth->pem_str = OPENSSL_strdup(pem_str);
if (!ameth->pem_str)
goto err;
}
return ameth;
err:
EVP_PKEY_asn1_free(ameth);
return NULL;
}
void EVP_PKEY_asn1_copy(EVP_PKEY_ASN1_METHOD *dst,
const EVP_PKEY_ASN1_METHOD *src)
{
dst->pub_decode = src->pub_decode;
dst->pub_encode = src->pub_encode;
dst->pub_cmp = src->pub_cmp;
dst->pub_print = src->pub_print;
dst->priv_decode = src->priv_decode;
dst->priv_encode = src->priv_encode;
dst->priv_print = src->priv_print;
dst->old_priv_encode = src->old_priv_encode;
dst->old_priv_decode = src->old_priv_decode;
dst->pkey_size = src->pkey_size;
dst->pkey_bits = src->pkey_bits;
dst->param_decode = src->param_decode;
dst->param_encode = src->param_encode;
dst->param_missing = src->param_missing;
dst->param_copy = src->param_copy;
dst->param_cmp = src->param_cmp;
dst->param_print = src->param_print;
dst->pkey_free = src->pkey_free;
dst->pkey_ctrl = src->pkey_ctrl;
dst->item_sign = src->item_sign;
dst->item_verify = src->item_verify;
dst->siginf_set = src->siginf_set;
dst->pkey_check = src->pkey_check;
}
void EVP_PKEY_asn1_free(EVP_PKEY_ASN1_METHOD *ameth)
{
if (ameth && (ameth->pkey_flags & ASN1_PKEY_DYNAMIC)) {
OPENSSL_free(ameth->pem_str);
OPENSSL_free(ameth->info);
OPENSSL_free(ameth);
}
}
void EVP_PKEY_asn1_set_public(EVP_PKEY_ASN1_METHOD *ameth,
int (*pub_decode) (EVP_PKEY *pk,
X509_PUBKEY *pub),
int (*pub_encode) (X509_PUBKEY *pub,
const EVP_PKEY *pk),
int (*pub_cmp) (const EVP_PKEY *a,
const EVP_PKEY *b),
int (*pub_print) (BIO *out,
const EVP_PKEY *pkey,
int indent, ASN1_PCTX *pctx),
int (*pkey_size) (const EVP_PKEY *pk),
int (*pkey_bits) (const EVP_PKEY *pk))
{
ameth->pub_decode = pub_decode;
ameth->pub_encode = pub_encode;
ameth->pub_cmp = pub_cmp;
ameth->pub_print = pub_print;
ameth->pkey_size = pkey_size;
ameth->pkey_bits = pkey_bits;
}
void EVP_PKEY_asn1_set_private(EVP_PKEY_ASN1_METHOD *ameth,
int (*priv_decode) (EVP_PKEY *pk,
const PKCS8_PRIV_KEY_INFO
*p8inf),
int (*priv_encode) (PKCS8_PRIV_KEY_INFO *p8,
const EVP_PKEY *pk),
int (*priv_print) (BIO *out,
const EVP_PKEY *pkey,
int indent,
ASN1_PCTX *pctx))
{
ameth->priv_decode = priv_decode;
ameth->priv_encode = priv_encode;
ameth->priv_print = priv_print;
}
void EVP_PKEY_asn1_set_param(EVP_PKEY_ASN1_METHOD *ameth,
int (*param_decode) (EVP_PKEY *pkey,
const unsigned char **pder,
int derlen),
int (*param_encode) (const EVP_PKEY *pkey,
unsigned char **pder),
int (*param_missing) (const EVP_PKEY *pk),
int (*param_copy) (EVP_PKEY *to,
const EVP_PKEY *from),
int (*param_cmp) (const EVP_PKEY *a,
const EVP_PKEY *b),
int (*param_print) (BIO *out,
const EVP_PKEY *pkey,
int indent, ASN1_PCTX *pctx))
{
ameth->param_decode = param_decode;
ameth->param_encode = param_encode;
ameth->param_missing = param_missing;
ameth->param_copy = param_copy;
ameth->param_cmp = param_cmp;
ameth->param_print = param_print;
}
void EVP_PKEY_asn1_set_free(EVP_PKEY_ASN1_METHOD *ameth,
void (*pkey_free) (EVP_PKEY *pkey))
{
ameth->pkey_free = pkey_free;
}
void EVP_PKEY_asn1_set_ctrl(EVP_PKEY_ASN1_METHOD *ameth,
int (*pkey_ctrl) (EVP_PKEY *pkey, int op,
long arg1, void *arg2))
{
ameth->pkey_ctrl = pkey_ctrl;
}
void EVP_PKEY_asn1_set_security_bits(EVP_PKEY_ASN1_METHOD *ameth,
int (*pkey_security_bits) (const EVP_PKEY
*pk))
{
ameth->pkey_security_bits = pkey_security_bits;
}
void EVP_PKEY_asn1_set_item(EVP_PKEY_ASN1_METHOD *ameth,
int (*item_verify) (EVP_MD_CTX *ctx,
const ASN1_ITEM *it,
void *asn,
X509_ALGOR *a,
ASN1_BIT_STRING *sig,
EVP_PKEY *pkey),
int (*item_sign) (EVP_MD_CTX *ctx,
const ASN1_ITEM *it,
void *asn,
X509_ALGOR *alg1,
X509_ALGOR *alg2,
ASN1_BIT_STRING *sig))
{
ameth->item_sign = item_sign;
ameth->item_verify = item_verify;
}
void EVP_PKEY_asn1_set_siginf(EVP_PKEY_ASN1_METHOD *ameth,
int (*siginf_set) (X509_SIG_INFO *siginf,
const X509_ALGOR *alg,
const ASN1_STRING *sig))
{
ameth->siginf_set = siginf_set;
}
void EVP_PKEY_asn1_set_check(EVP_PKEY_ASN1_METHOD *ameth,
int (*pkey_check) (const EVP_PKEY *pk))
{
ameth->pkey_check = pkey_check;
}
void EVP_PKEY_asn1_set_public_check(EVP_PKEY_ASN1_METHOD *ameth,
int (*pkey_pub_check) (const EVP_PKEY *pk))
{
ameth->pkey_public_check = pkey_pub_check;
}
void EVP_PKEY_asn1_set_param_check(EVP_PKEY_ASN1_METHOD *ameth,
int (*pkey_param_check) (const EVP_PKEY *pk))
{
ameth->pkey_param_check = pkey_param_check;
}
void EVP_PKEY_asn1_set_set_priv_key(EVP_PKEY_ASN1_METHOD *ameth,
int (*set_priv_key) (EVP_PKEY *pk,
const unsigned char
*priv,
size_t len))
{
ameth->set_priv_key = set_priv_key;
}
void EVP_PKEY_asn1_set_set_pub_key(EVP_PKEY_ASN1_METHOD *ameth,
int (*set_pub_key) (EVP_PKEY *pk,
const unsigned char *pub,
size_t len))
{
ameth->set_pub_key = set_pub_key;
}
void EVP_PKEY_asn1_set_get_priv_key(EVP_PKEY_ASN1_METHOD *ameth,
int (*get_priv_key) (const EVP_PKEY *pk,
unsigned char *priv,
size_t *len))
{
ameth->get_priv_key = get_priv_key;
}
void EVP_PKEY_asn1_set_get_pub_key(EVP_PKEY_ASN1_METHOD *ameth,
int (*get_pub_key) (const EVP_PKEY *pk,
unsigned char *pub,
size_t *len))
{
ameth->get_pub_key = get_pub_key;
}

View file

@ -0,0 +1,350 @@
/*
* Generated by util/mkerr.pl DO NOT EDIT
* Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <openssl/err.h>
#include <openssl/asn1err.h>
#ifndef OPENSSL_NO_ERR
static const ERR_STRING_DATA ASN1_str_functs[] = {
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_A2D_ASN1_OBJECT, 0), "a2d_ASN1_OBJECT"},
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_A2I_ASN1_INTEGER, 0), "a2i_ASN1_INTEGER"},
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_A2I_ASN1_STRING, 0), "a2i_ASN1_STRING"},
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_APPEND_EXP, 0), "append_exp"},
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_BIO_INIT, 0), "asn1_bio_init"},
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_BIT_STRING_SET_BIT, 0),
"ASN1_BIT_STRING_set_bit"},
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_CB, 0), "asn1_cb"},
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_CHECK_TLEN, 0), "asn1_check_tlen"},
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_COLLECT, 0), "asn1_collect"},
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_D2I_EX_PRIMITIVE, 0),
"asn1_d2i_ex_primitive"},
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_D2I_FP, 0), "ASN1_d2i_fp"},
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_D2I_READ_BIO, 0), "asn1_d2i_read_bio"},
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_DIGEST, 0), "ASN1_digest"},
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_DO_ADB, 0), "asn1_do_adb"},
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_DO_LOCK, 0), "asn1_do_lock"},
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_DUP, 0), "ASN1_dup"},
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_ENC_SAVE, 0), "asn1_enc_save"},
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_EX_C2I, 0), "asn1_ex_c2i"},
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_FIND_END, 0), "asn1_find_end"},
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_GENERALIZEDTIME_ADJ, 0),
"ASN1_GENERALIZEDTIME_adj"},
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_GENERATE_V3, 0), "ASN1_generate_v3"},
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_GET_INT64, 0), "asn1_get_int64"},
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_GET_OBJECT, 0), "ASN1_get_object"},
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_GET_UINT64, 0), "asn1_get_uint64"},
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_I2D_BIO, 0), "ASN1_i2d_bio"},
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_I2D_FP, 0), "ASN1_i2d_fp"},
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_ITEM_D2I_FP, 0), "ASN1_item_d2i_fp"},
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_ITEM_DUP, 0), "ASN1_item_dup"},
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_ITEM_EMBED_D2I, 0),
"asn1_item_embed_d2i"},
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_ITEM_EMBED_NEW, 0),
"asn1_item_embed_new"},
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_ITEM_FLAGS_I2D, 0),
"asn1_item_flags_i2d"},
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_ITEM_I2D_BIO, 0), "ASN1_item_i2d_bio"},
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_ITEM_I2D_FP, 0), "ASN1_item_i2d_fp"},
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_ITEM_PACK, 0), "ASN1_item_pack"},
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_ITEM_SIGN, 0), "ASN1_item_sign"},
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_ITEM_SIGN_CTX, 0),
"ASN1_item_sign_ctx"},
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_ITEM_UNPACK, 0), "ASN1_item_unpack"},
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_ITEM_VERIFY, 0), "ASN1_item_verify"},
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_MBSTRING_NCOPY, 0),
"ASN1_mbstring_ncopy"},
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_OBJECT_NEW, 0), "ASN1_OBJECT_new"},
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_OUTPUT_DATA, 0), "asn1_output_data"},
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_PCTX_NEW, 0), "ASN1_PCTX_new"},
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_PRIMITIVE_NEW, 0),
"asn1_primitive_new"},
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_SCTX_NEW, 0), "ASN1_SCTX_new"},
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_SIGN, 0), "ASN1_sign"},
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_STR2TYPE, 0), "asn1_str2type"},
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_STRING_GET_INT64, 0),
"asn1_string_get_int64"},
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_STRING_GET_UINT64, 0),
"asn1_string_get_uint64"},
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_STRING_SET, 0), "ASN1_STRING_set"},
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_STRING_TABLE_ADD, 0),
"ASN1_STRING_TABLE_add"},
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_STRING_TO_BN, 0), "asn1_string_to_bn"},
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_STRING_TYPE_NEW, 0),
"ASN1_STRING_type_new"},
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_TEMPLATE_EX_D2I, 0),
"asn1_template_ex_d2i"},
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_TEMPLATE_NEW, 0), "asn1_template_new"},
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_TEMPLATE_NOEXP_D2I, 0),
"asn1_template_noexp_d2i"},
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_TIME_ADJ, 0), "ASN1_TIME_adj"},
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_TYPE_GET_INT_OCTETSTRING, 0),
"ASN1_TYPE_get_int_octetstring"},
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_TYPE_GET_OCTETSTRING, 0),
"ASN1_TYPE_get_octetstring"},
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_UTCTIME_ADJ, 0), "ASN1_UTCTIME_adj"},
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_VERIFY, 0), "ASN1_verify"},
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_B64_READ_ASN1, 0), "b64_read_asn1"},
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_B64_WRITE_ASN1, 0), "B64_write_ASN1"},
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_BIO_NEW_NDEF, 0), "BIO_new_NDEF"},
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_BITSTR_CB, 0), "bitstr_cb"},
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_BN_TO_ASN1_STRING, 0), "bn_to_asn1_string"},
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_C2I_ASN1_BIT_STRING, 0),
"c2i_ASN1_BIT_STRING"},
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_C2I_ASN1_INTEGER, 0), "c2i_ASN1_INTEGER"},
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_C2I_ASN1_OBJECT, 0), "c2i_ASN1_OBJECT"},
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_C2I_IBUF, 0), "c2i_ibuf"},
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_C2I_UINT64_INT, 0), "c2i_uint64_int"},
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_COLLECT_DATA, 0), "collect_data"},
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_D2I_ASN1_OBJECT, 0), "d2i_ASN1_OBJECT"},
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_D2I_ASN1_UINTEGER, 0), "d2i_ASN1_UINTEGER"},
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_D2I_AUTOPRIVATEKEY, 0),
"d2i_AutoPrivateKey"},
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_D2I_PRIVATEKEY, 0), "d2i_PrivateKey"},
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_D2I_PUBLICKEY, 0), "d2i_PublicKey"},
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_DO_BUF, 0), "do_buf"},
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_DO_CREATE, 0), "do_create"},
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_DO_DUMP, 0), "do_dump"},
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_DO_TCREATE, 0), "do_tcreate"},
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_I2A_ASN1_OBJECT, 0), "i2a_ASN1_OBJECT"},
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_I2D_ASN1_BIO_STREAM, 0),
"i2d_ASN1_bio_stream"},
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_I2D_ASN1_OBJECT, 0), "i2d_ASN1_OBJECT"},
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_I2D_DSA_PUBKEY, 0), "i2d_DSA_PUBKEY"},
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_I2D_EC_PUBKEY, 0), "i2d_EC_PUBKEY"},
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_I2D_PRIVATEKEY, 0), "i2d_PrivateKey"},
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_I2D_PUBLICKEY, 0), "i2d_PublicKey"},
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_I2D_RSA_PUBKEY, 0), "i2d_RSA_PUBKEY"},
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_LONG_C2I, 0), "long_c2i"},
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_NDEF_PREFIX, 0), "ndef_prefix"},
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_NDEF_SUFFIX, 0), "ndef_suffix"},
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_OID_MODULE_INIT, 0), "oid_module_init"},
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_PARSE_TAGGING, 0), "parse_tagging"},
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_PKCS5_PBE2_SET_IV, 0), "PKCS5_pbe2_set_iv"},
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_PKCS5_PBE2_SET_SCRYPT, 0),
"PKCS5_pbe2_set_scrypt"},
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_PKCS5_PBE_SET, 0), "PKCS5_pbe_set"},
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_PKCS5_PBE_SET0_ALGOR, 0),
"PKCS5_pbe_set0_algor"},
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_PKCS5_PBKDF2_SET, 0), "PKCS5_pbkdf2_set"},
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_PKCS5_SCRYPT_SET, 0), "pkcs5_scrypt_set"},
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_SMIME_READ_ASN1, 0), "SMIME_read_ASN1"},
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_SMIME_TEXT, 0), "SMIME_text"},
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_STABLE_GET, 0), "stable_get"},
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_STBL_MODULE_INIT, 0), "stbl_module_init"},
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_UINT32_C2I, 0), "uint32_c2i"},
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_UINT32_NEW, 0), "uint32_new"},
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_UINT64_C2I, 0), "uint64_c2i"},
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_UINT64_NEW, 0), "uint64_new"},
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_X509_CRL_ADD0_REVOKED, 0),
"X509_CRL_add0_revoked"},
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_X509_INFO_NEW, 0), "X509_INFO_new"},
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_X509_NAME_ENCODE, 0), "x509_name_encode"},
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_X509_NAME_EX_D2I, 0), "x509_name_ex_d2i"},
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_X509_NAME_EX_NEW, 0), "x509_name_ex_new"},
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_X509_PKEY_NEW, 0), "X509_PKEY_new"},
{0, NULL}
};
static const ERR_STRING_DATA ASN1_str_reasons[] = {
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_ADDING_OBJECT), "adding object"},
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_ASN1_PARSE_ERROR), "asn1 parse error"},
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_ASN1_SIG_PARSE_ERROR),
"asn1 sig parse error"},
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_AUX_ERROR), "aux error"},
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_BAD_OBJECT_HEADER), "bad object header"},
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_BMPSTRING_IS_WRONG_LENGTH),
"bmpstring is wrong length"},
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_BN_LIB), "bn lib"},
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_BOOLEAN_IS_WRONG_LENGTH),
"boolean is wrong length"},
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_BUFFER_TOO_SMALL), "buffer too small"},
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_CIPHER_HAS_NO_OBJECT_IDENTIFIER),
"cipher has no object identifier"},
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_CONTEXT_NOT_INITIALISED),
"context not initialised"},
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_DATA_IS_WRONG), "data is wrong"},
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_DECODE_ERROR), "decode error"},
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_DEPTH_EXCEEDED), "depth exceeded"},
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_DIGEST_AND_KEY_TYPE_NOT_SUPPORTED),
"digest and key type not supported"},
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_ENCODE_ERROR), "encode error"},
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_ERROR_GETTING_TIME),
"error getting time"},
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_ERROR_LOADING_SECTION),
"error loading section"},
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_ERROR_SETTING_CIPHER_PARAMS),
"error setting cipher params"},
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_EXPECTING_AN_INTEGER),
"expecting an integer"},
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_EXPECTING_AN_OBJECT),
"expecting an object"},
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_EXPLICIT_LENGTH_MISMATCH),
"explicit length mismatch"},
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_EXPLICIT_TAG_NOT_CONSTRUCTED),
"explicit tag not constructed"},
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_FIELD_MISSING), "field missing"},
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_FIRST_NUM_TOO_LARGE),
"first num too large"},
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_HEADER_TOO_LONG), "header too long"},
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_ILLEGAL_BITSTRING_FORMAT),
"illegal bitstring format"},
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_ILLEGAL_BOOLEAN), "illegal boolean"},
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_ILLEGAL_CHARACTERS),
"illegal characters"},
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_ILLEGAL_FORMAT), "illegal format"},
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_ILLEGAL_HEX), "illegal hex"},
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_ILLEGAL_IMPLICIT_TAG),
"illegal implicit tag"},
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_ILLEGAL_INTEGER), "illegal integer"},
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_ILLEGAL_NEGATIVE_VALUE),
"illegal negative value"},
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_ILLEGAL_NESTED_TAGGING),
"illegal nested tagging"},
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_ILLEGAL_NULL), "illegal null"},
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_ILLEGAL_NULL_VALUE),
"illegal null value"},
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_ILLEGAL_OBJECT), "illegal object"},
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_ILLEGAL_OPTIONAL_ANY),
"illegal optional any"},
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_ILLEGAL_OPTIONS_ON_ITEM_TEMPLATE),
"illegal options on item template"},
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_ILLEGAL_PADDING), "illegal padding"},
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_ILLEGAL_TAGGED_ANY),
"illegal tagged any"},
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_ILLEGAL_TIME_VALUE),
"illegal time value"},
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_ILLEGAL_ZERO_CONTENT),
"illegal zero content"},
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_INTEGER_NOT_ASCII_FORMAT),
"integer not ascii format"},
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_INTEGER_TOO_LARGE_FOR_LONG),
"integer too large for long"},
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_INVALID_BIT_STRING_BITS_LEFT),
"invalid bit string bits left"},
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_INVALID_BMPSTRING_LENGTH),
"invalid bmpstring length"},
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_INVALID_DIGIT), "invalid digit"},
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_INVALID_MIME_TYPE), "invalid mime type"},
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_INVALID_MODIFIER), "invalid modifier"},
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_INVALID_NUMBER), "invalid number"},
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_INVALID_OBJECT_ENCODING),
"invalid object encoding"},
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_INVALID_SCRYPT_PARAMETERS),
"invalid scrypt parameters"},
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_INVALID_SEPARATOR), "invalid separator"},
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_INVALID_STRING_TABLE_VALUE),
"invalid string table value"},
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_INVALID_UNIVERSALSTRING_LENGTH),
"invalid universalstring length"},
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_INVALID_UTF8STRING),
"invalid utf8string"},
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_INVALID_VALUE), "invalid value"},
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_LIST_ERROR), "list error"},
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_MIME_NO_CONTENT_TYPE),
"mime no content type"},
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_MIME_PARSE_ERROR), "mime parse error"},
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_MIME_SIG_PARSE_ERROR),
"mime sig parse error"},
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_MISSING_EOC), "missing eoc"},
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_MISSING_SECOND_NUMBER),
"missing second number"},
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_MISSING_VALUE), "missing value"},
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_MSTRING_NOT_UNIVERSAL),
"mstring not universal"},
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_MSTRING_WRONG_TAG), "mstring wrong tag"},
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_NESTED_ASN1_STRING),
"nested asn1 string"},
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_NESTED_TOO_DEEP), "nested too deep"},
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_NON_HEX_CHARACTERS),
"non hex characters"},
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_NOT_ASCII_FORMAT), "not ascii format"},
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_NOT_ENOUGH_DATA), "not enough data"},
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_NO_CONTENT_TYPE), "no content type"},
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_NO_MATCHING_CHOICE_TYPE),
"no matching choice type"},
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_NO_MULTIPART_BODY_FAILURE),
"no multipart body failure"},
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_NO_MULTIPART_BOUNDARY),
"no multipart boundary"},
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_NO_SIG_CONTENT_TYPE),
"no sig content type"},
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_NULL_IS_WRONG_LENGTH),
"null is wrong length"},
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_OBJECT_NOT_ASCII_FORMAT),
"object not ascii format"},
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_ODD_NUMBER_OF_CHARS),
"odd number of chars"},
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_SECOND_NUMBER_TOO_LARGE),
"second number too large"},
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_SEQUENCE_LENGTH_MISMATCH),
"sequence length mismatch"},
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_SEQUENCE_NOT_CONSTRUCTED),
"sequence not constructed"},
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_SEQUENCE_OR_SET_NEEDS_CONFIG),
"sequence or set needs config"},
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_SHORT_LINE), "short line"},
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_SIG_INVALID_MIME_TYPE),
"sig invalid mime type"},
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_STREAMING_NOT_SUPPORTED),
"streaming not supported"},
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_STRING_TOO_LONG), "string too long"},
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_STRING_TOO_SHORT), "string too short"},
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_THE_ASN1_OBJECT_IDENTIFIER_IS_NOT_KNOWN_FOR_THIS_MD),
"the asn1 object identifier is not known for this md"},
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_TIME_NOT_ASCII_FORMAT),
"time not ascii format"},
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_TOO_LARGE), "too large"},
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_TOO_LONG), "too long"},
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_TOO_SMALL), "too small"},
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_TYPE_NOT_CONSTRUCTED),
"type not constructed"},
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_TYPE_NOT_PRIMITIVE),
"type not primitive"},
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_UNEXPECTED_EOC), "unexpected eoc"},
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_UNIVERSALSTRING_IS_WRONG_LENGTH),
"universalstring is wrong length"},
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_UNKNOWN_FORMAT), "unknown format"},
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_UNKNOWN_MESSAGE_DIGEST_ALGORITHM),
"unknown message digest algorithm"},
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_UNKNOWN_OBJECT_TYPE),
"unknown object type"},
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_UNKNOWN_PUBLIC_KEY_TYPE),
"unknown public key type"},
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_UNKNOWN_SIGNATURE_ALGORITHM),
"unknown signature algorithm"},
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_UNKNOWN_TAG), "unknown tag"},
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_UNSUPPORTED_ANY_DEFINED_BY_TYPE),
"unsupported any defined by type"},
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_UNSUPPORTED_CIPHER),
"unsupported cipher"},
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_UNSUPPORTED_PUBLIC_KEY_TYPE),
"unsupported public key type"},
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_UNSUPPORTED_TYPE), "unsupported type"},
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_WRONG_INTEGER_TYPE),
"wrong integer type"},
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_WRONG_PUBLIC_KEY_TYPE),
"wrong public key type"},
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_WRONG_TAG), "wrong tag"},
{0, NULL}
};
#endif
int ERR_load_ASN1_strings(void)
{
#ifndef OPENSSL_NO_ERR
if (ERR_func_error_string(ASN1_str_functs[0].error) == NULL) {
ERR_load_strings_const(ASN1_str_functs);
ERR_load_strings_const(ASN1_str_reasons);
}
#endif
return 1;
}

View file

@ -0,0 +1,789 @@
/*
* Copyright 2002-2016 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include "internal/cryptlib.h"
#include <openssl/asn1.h>
#include <openssl/x509v3.h>
#define ASN1_GEN_FLAG 0x10000
#define ASN1_GEN_FLAG_IMP (ASN1_GEN_FLAG|1)
#define ASN1_GEN_FLAG_EXP (ASN1_GEN_FLAG|2)
#define ASN1_GEN_FLAG_TAG (ASN1_GEN_FLAG|3)
#define ASN1_GEN_FLAG_BITWRAP (ASN1_GEN_FLAG|4)
#define ASN1_GEN_FLAG_OCTWRAP (ASN1_GEN_FLAG|5)
#define ASN1_GEN_FLAG_SEQWRAP (ASN1_GEN_FLAG|6)
#define ASN1_GEN_FLAG_SETWRAP (ASN1_GEN_FLAG|7)
#define ASN1_GEN_FLAG_FORMAT (ASN1_GEN_FLAG|8)
#define ASN1_GEN_STR(str,val) {str, sizeof(str) - 1, val}
#define ASN1_FLAG_EXP_MAX 20
/* Maximum number of nested sequences */
#define ASN1_GEN_SEQ_MAX_DEPTH 50
/* Input formats */
/* ASCII: default */
#define ASN1_GEN_FORMAT_ASCII 1
/* UTF8 */
#define ASN1_GEN_FORMAT_UTF8 2
/* Hex */
#define ASN1_GEN_FORMAT_HEX 3
/* List of bits */
#define ASN1_GEN_FORMAT_BITLIST 4
struct tag_name_st {
const char *strnam;
int len;
int tag;
};
typedef struct {
int exp_tag;
int exp_class;
int exp_constructed;
int exp_pad;
long exp_len;
} tag_exp_type;
typedef struct {
int imp_tag;
int imp_class;
int utype;
int format;
const char *str;
tag_exp_type exp_list[ASN1_FLAG_EXP_MAX];
int exp_count;
} tag_exp_arg;
static ASN1_TYPE *generate_v3(const char *str, X509V3_CTX *cnf, int depth,
int *perr);
static int bitstr_cb(const char *elem, int len, void *bitstr);
static int asn1_cb(const char *elem, int len, void *bitstr);
static int append_exp(tag_exp_arg *arg, int exp_tag, int exp_class,
int exp_constructed, int exp_pad, int imp_ok);
static int parse_tagging(const char *vstart, int vlen, int *ptag,
int *pclass);
static ASN1_TYPE *asn1_multi(int utype, const char *section, X509V3_CTX *cnf,
int depth, int *perr);
static ASN1_TYPE *asn1_str2type(const char *str, int format, int utype);
static int asn1_str2tag(const char *tagstr, int len);
ASN1_TYPE *ASN1_generate_nconf(const char *str, CONF *nconf)
{
X509V3_CTX cnf;
if (!nconf)
return ASN1_generate_v3(str, NULL);
X509V3_set_nconf(&cnf, nconf);
return ASN1_generate_v3(str, &cnf);
}
ASN1_TYPE *ASN1_generate_v3(const char *str, X509V3_CTX *cnf)
{
int err = 0;
ASN1_TYPE *ret = generate_v3(str, cnf, 0, &err);
if (err)
ASN1err(ASN1_F_ASN1_GENERATE_V3, err);
return ret;
}
static ASN1_TYPE *generate_v3(const char *str, X509V3_CTX *cnf, int depth,
int *perr)
{
ASN1_TYPE *ret;
tag_exp_arg asn1_tags;
tag_exp_type *etmp;
int i, len;
unsigned char *orig_der = NULL, *new_der = NULL;
const unsigned char *cpy_start;
unsigned char *p;
const unsigned char *cp;
int cpy_len;
long hdr_len = 0;
int hdr_constructed = 0, hdr_tag, hdr_class;
int r;
asn1_tags.imp_tag = -1;
asn1_tags.imp_class = -1;
asn1_tags.format = ASN1_GEN_FORMAT_ASCII;
asn1_tags.exp_count = 0;
if (CONF_parse_list(str, ',', 1, asn1_cb, &asn1_tags) != 0) {
*perr = ASN1_R_UNKNOWN_TAG;
return NULL;
}
if ((asn1_tags.utype == V_ASN1_SEQUENCE)
|| (asn1_tags.utype == V_ASN1_SET)) {
if (!cnf) {
*perr = ASN1_R_SEQUENCE_OR_SET_NEEDS_CONFIG;
return NULL;
}
if (depth >= ASN1_GEN_SEQ_MAX_DEPTH) {
*perr = ASN1_R_ILLEGAL_NESTED_TAGGING;
return NULL;
}
ret = asn1_multi(asn1_tags.utype, asn1_tags.str, cnf, depth, perr);
} else
ret = asn1_str2type(asn1_tags.str, asn1_tags.format, asn1_tags.utype);
if (!ret)
return NULL;
/* If no tagging return base type */
if ((asn1_tags.imp_tag == -1) && (asn1_tags.exp_count == 0))
return ret;
/* Generate the encoding */
cpy_len = i2d_ASN1_TYPE(ret, &orig_der);
ASN1_TYPE_free(ret);
ret = NULL;
/* Set point to start copying for modified encoding */
cpy_start = orig_der;
/* Do we need IMPLICIT tagging? */
if (asn1_tags.imp_tag != -1) {
/* If IMPLICIT we will replace the underlying tag */
/* Skip existing tag+len */
r = ASN1_get_object(&cpy_start, &hdr_len, &hdr_tag, &hdr_class,
cpy_len);
if (r & 0x80)
goto err;
/* Update copy length */
cpy_len -= cpy_start - orig_der;
/*
* For IMPLICIT tagging the length should match the original length
* and constructed flag should be consistent.
*/
if (r & 0x1) {
/* Indefinite length constructed */
hdr_constructed = 2;
hdr_len = 0;
} else
/* Just retain constructed flag */
hdr_constructed = r & V_ASN1_CONSTRUCTED;
/*
* Work out new length with IMPLICIT tag: ignore constructed because
* it will mess up if indefinite length
*/
len = ASN1_object_size(0, hdr_len, asn1_tags.imp_tag);
} else
len = cpy_len;
/* Work out length in any EXPLICIT, starting from end */
for (i = 0, etmp = asn1_tags.exp_list + asn1_tags.exp_count - 1;
i < asn1_tags.exp_count; i++, etmp--) {
/* Content length: number of content octets + any padding */
len += etmp->exp_pad;
etmp->exp_len = len;
/* Total object length: length including new header */
len = ASN1_object_size(0, len, etmp->exp_tag);
}
/* Allocate buffer for new encoding */
new_der = OPENSSL_malloc(len);
if (new_der == NULL)
goto err;
/* Generate tagged encoding */
p = new_der;
/* Output explicit tags first */
for (i = 0, etmp = asn1_tags.exp_list; i < asn1_tags.exp_count;
i++, etmp++) {
ASN1_put_object(&p, etmp->exp_constructed, etmp->exp_len,
etmp->exp_tag, etmp->exp_class);
if (etmp->exp_pad)
*p++ = 0;
}
/* If IMPLICIT, output tag */
if (asn1_tags.imp_tag != -1) {
if (asn1_tags.imp_class == V_ASN1_UNIVERSAL
&& (asn1_tags.imp_tag == V_ASN1_SEQUENCE
|| asn1_tags.imp_tag == V_ASN1_SET))
hdr_constructed = V_ASN1_CONSTRUCTED;
ASN1_put_object(&p, hdr_constructed, hdr_len,
asn1_tags.imp_tag, asn1_tags.imp_class);
}
/* Copy across original encoding */
memcpy(p, cpy_start, cpy_len);
cp = new_der;
/* Obtain new ASN1_TYPE structure */
ret = d2i_ASN1_TYPE(NULL, &cp, len);
err:
OPENSSL_free(orig_der);
OPENSSL_free(new_der);
return ret;
}
static int asn1_cb(const char *elem, int len, void *bitstr)
{
tag_exp_arg *arg = bitstr;
int i;
int utype;
int vlen = 0;
const char *p, *vstart = NULL;
int tmp_tag, tmp_class;
if (elem == NULL)
return -1;
for (i = 0, p = elem; i < len; p++, i++) {
/* Look for the ':' in name value pairs */
if (*p == ':') {
vstart = p + 1;
vlen = len - (vstart - elem);
len = p - elem;
break;
}
}
utype = asn1_str2tag(elem, len);
if (utype == -1) {
ASN1err(ASN1_F_ASN1_CB, ASN1_R_UNKNOWN_TAG);
ERR_add_error_data(2, "tag=", elem);
return -1;
}
/* If this is not a modifier mark end of string and exit */
if (!(utype & ASN1_GEN_FLAG)) {
arg->utype = utype;
arg->str = vstart;
/* If no value and not end of string, error */
if (!vstart && elem[len]) {
ASN1err(ASN1_F_ASN1_CB, ASN1_R_MISSING_VALUE);
return -1;
}
return 0;
}
switch (utype) {
case ASN1_GEN_FLAG_IMP:
/* Check for illegal multiple IMPLICIT tagging */
if (arg->imp_tag != -1) {
ASN1err(ASN1_F_ASN1_CB, ASN1_R_ILLEGAL_NESTED_TAGGING);
return -1;
}
if (!parse_tagging(vstart, vlen, &arg->imp_tag, &arg->imp_class))
return -1;
break;
case ASN1_GEN_FLAG_EXP:
if (!parse_tagging(vstart, vlen, &tmp_tag, &tmp_class))
return -1;
if (!append_exp(arg, tmp_tag, tmp_class, 1, 0, 0))
return -1;
break;
case ASN1_GEN_FLAG_SEQWRAP:
if (!append_exp(arg, V_ASN1_SEQUENCE, V_ASN1_UNIVERSAL, 1, 0, 1))
return -1;
break;
case ASN1_GEN_FLAG_SETWRAP:
if (!append_exp(arg, V_ASN1_SET, V_ASN1_UNIVERSAL, 1, 0, 1))
return -1;
break;
case ASN1_GEN_FLAG_BITWRAP:
if (!append_exp(arg, V_ASN1_BIT_STRING, V_ASN1_UNIVERSAL, 0, 1, 1))
return -1;
break;
case ASN1_GEN_FLAG_OCTWRAP:
if (!append_exp(arg, V_ASN1_OCTET_STRING, V_ASN1_UNIVERSAL, 0, 0, 1))
return -1;
break;
case ASN1_GEN_FLAG_FORMAT:
if (!vstart) {
ASN1err(ASN1_F_ASN1_CB, ASN1_R_UNKNOWN_FORMAT);
return -1;
}
if (strncmp(vstart, "ASCII", 5) == 0)
arg->format = ASN1_GEN_FORMAT_ASCII;
else if (strncmp(vstart, "UTF8", 4) == 0)
arg->format = ASN1_GEN_FORMAT_UTF8;
else if (strncmp(vstart, "HEX", 3) == 0)
arg->format = ASN1_GEN_FORMAT_HEX;
else if (strncmp(vstart, "BITLIST", 7) == 0)
arg->format = ASN1_GEN_FORMAT_BITLIST;
else {
ASN1err(ASN1_F_ASN1_CB, ASN1_R_UNKNOWN_FORMAT);
return -1;
}
break;
}
return 1;
}
static int parse_tagging(const char *vstart, int vlen, int *ptag, int *pclass)
{
char erch[2];
long tag_num;
char *eptr;
if (!vstart)
return 0;
tag_num = strtoul(vstart, &eptr, 10);
/* Check we haven't gone past max length: should be impossible */
if (eptr && *eptr && (eptr > vstart + vlen))
return 0;
if (tag_num < 0) {
ASN1err(ASN1_F_PARSE_TAGGING, ASN1_R_INVALID_NUMBER);
return 0;
}
*ptag = tag_num;
/* If we have non numeric characters, parse them */
if (eptr)
vlen -= eptr - vstart;
else
vlen = 0;
if (vlen) {
switch (*eptr) {
case 'U':
*pclass = V_ASN1_UNIVERSAL;
break;
case 'A':
*pclass = V_ASN1_APPLICATION;
break;
case 'P':
*pclass = V_ASN1_PRIVATE;
break;
case 'C':
*pclass = V_ASN1_CONTEXT_SPECIFIC;
break;
default:
erch[0] = *eptr;
erch[1] = 0;
ASN1err(ASN1_F_PARSE_TAGGING, ASN1_R_INVALID_MODIFIER);
ERR_add_error_data(2, "Char=", erch);
return 0;
}
} else
*pclass = V_ASN1_CONTEXT_SPECIFIC;
return 1;
}
/* Handle multiple types: SET and SEQUENCE */
static ASN1_TYPE *asn1_multi(int utype, const char *section, X509V3_CTX *cnf,
int depth, int *perr)
{
ASN1_TYPE *ret = NULL;
STACK_OF(ASN1_TYPE) *sk = NULL;
STACK_OF(CONF_VALUE) *sect = NULL;
unsigned char *der = NULL;
int derlen;
int i;
sk = sk_ASN1_TYPE_new_null();
if (!sk)
goto bad;
if (section) {
if (!cnf)
goto bad;
sect = X509V3_get_section(cnf, (char *)section);
if (!sect)
goto bad;
for (i = 0; i < sk_CONF_VALUE_num(sect); i++) {
ASN1_TYPE *typ =
generate_v3(sk_CONF_VALUE_value(sect, i)->value, cnf,
depth + 1, perr);
if (!typ)
goto bad;
if (!sk_ASN1_TYPE_push(sk, typ))
goto bad;
}
}
/*
* Now we has a STACK of the components, convert to the correct form
*/
if (utype == V_ASN1_SET)
derlen = i2d_ASN1_SET_ANY(sk, &der);
else
derlen = i2d_ASN1_SEQUENCE_ANY(sk, &der);
if (derlen < 0)
goto bad;
if ((ret = ASN1_TYPE_new()) == NULL)
goto bad;
if ((ret->value.asn1_string = ASN1_STRING_type_new(utype)) == NULL)
goto bad;
ret->type = utype;
ret->value.asn1_string->data = der;
ret->value.asn1_string->length = derlen;
der = NULL;
bad:
OPENSSL_free(der);
sk_ASN1_TYPE_pop_free(sk, ASN1_TYPE_free);
X509V3_section_free(cnf, sect);
return ret;
}
static int append_exp(tag_exp_arg *arg, int exp_tag, int exp_class,
int exp_constructed, int exp_pad, int imp_ok)
{
tag_exp_type *exp_tmp;
/* Can only have IMPLICIT if permitted */
if ((arg->imp_tag != -1) && !imp_ok) {
ASN1err(ASN1_F_APPEND_EXP, ASN1_R_ILLEGAL_IMPLICIT_TAG);
return 0;
}
if (arg->exp_count == ASN1_FLAG_EXP_MAX) {
ASN1err(ASN1_F_APPEND_EXP, ASN1_R_DEPTH_EXCEEDED);
return 0;
}
exp_tmp = &arg->exp_list[arg->exp_count++];
/*
* If IMPLICIT set tag to implicit value then reset implicit tag since it
* has been used.
*/
if (arg->imp_tag != -1) {
exp_tmp->exp_tag = arg->imp_tag;
exp_tmp->exp_class = arg->imp_class;
arg->imp_tag = -1;
arg->imp_class = -1;
} else {
exp_tmp->exp_tag = exp_tag;
exp_tmp->exp_class = exp_class;
}
exp_tmp->exp_constructed = exp_constructed;
exp_tmp->exp_pad = exp_pad;
return 1;
}
static int asn1_str2tag(const char *tagstr, int len)
{
unsigned int i;
static const struct tag_name_st *tntmp, tnst[] = {
ASN1_GEN_STR("BOOL", V_ASN1_BOOLEAN),
ASN1_GEN_STR("BOOLEAN", V_ASN1_BOOLEAN),
ASN1_GEN_STR("NULL", V_ASN1_NULL),
ASN1_GEN_STR("INT", V_ASN1_INTEGER),
ASN1_GEN_STR("INTEGER", V_ASN1_INTEGER),
ASN1_GEN_STR("ENUM", V_ASN1_ENUMERATED),
ASN1_GEN_STR("ENUMERATED", V_ASN1_ENUMERATED),
ASN1_GEN_STR("OID", V_ASN1_OBJECT),
ASN1_GEN_STR("OBJECT", V_ASN1_OBJECT),
ASN1_GEN_STR("UTCTIME", V_ASN1_UTCTIME),
ASN1_GEN_STR("UTC", V_ASN1_UTCTIME),
ASN1_GEN_STR("GENERALIZEDTIME", V_ASN1_GENERALIZEDTIME),
ASN1_GEN_STR("GENTIME", V_ASN1_GENERALIZEDTIME),
ASN1_GEN_STR("OCT", V_ASN1_OCTET_STRING),
ASN1_GEN_STR("OCTETSTRING", V_ASN1_OCTET_STRING),
ASN1_GEN_STR("BITSTR", V_ASN1_BIT_STRING),
ASN1_GEN_STR("BITSTRING", V_ASN1_BIT_STRING),
ASN1_GEN_STR("UNIVERSALSTRING", V_ASN1_UNIVERSALSTRING),
ASN1_GEN_STR("UNIV", V_ASN1_UNIVERSALSTRING),
ASN1_GEN_STR("IA5", V_ASN1_IA5STRING),
ASN1_GEN_STR("IA5STRING", V_ASN1_IA5STRING),
ASN1_GEN_STR("UTF8", V_ASN1_UTF8STRING),
ASN1_GEN_STR("UTF8String", V_ASN1_UTF8STRING),
ASN1_GEN_STR("BMP", V_ASN1_BMPSTRING),
ASN1_GEN_STR("BMPSTRING", V_ASN1_BMPSTRING),
ASN1_GEN_STR("VISIBLESTRING", V_ASN1_VISIBLESTRING),
ASN1_GEN_STR("VISIBLE", V_ASN1_VISIBLESTRING),
ASN1_GEN_STR("PRINTABLESTRING", V_ASN1_PRINTABLESTRING),
ASN1_GEN_STR("PRINTABLE", V_ASN1_PRINTABLESTRING),
ASN1_GEN_STR("T61", V_ASN1_T61STRING),
ASN1_GEN_STR("T61STRING", V_ASN1_T61STRING),
ASN1_GEN_STR("TELETEXSTRING", V_ASN1_T61STRING),
ASN1_GEN_STR("GeneralString", V_ASN1_GENERALSTRING),
ASN1_GEN_STR("GENSTR", V_ASN1_GENERALSTRING),
ASN1_GEN_STR("NUMERIC", V_ASN1_NUMERICSTRING),
ASN1_GEN_STR("NUMERICSTRING", V_ASN1_NUMERICSTRING),
/* Special cases */
ASN1_GEN_STR("SEQUENCE", V_ASN1_SEQUENCE),
ASN1_GEN_STR("SEQ", V_ASN1_SEQUENCE),
ASN1_GEN_STR("SET", V_ASN1_SET),
/* type modifiers */
/* Explicit tag */
ASN1_GEN_STR("EXP", ASN1_GEN_FLAG_EXP),
ASN1_GEN_STR("EXPLICIT", ASN1_GEN_FLAG_EXP),
/* Implicit tag */
ASN1_GEN_STR("IMP", ASN1_GEN_FLAG_IMP),
ASN1_GEN_STR("IMPLICIT", ASN1_GEN_FLAG_IMP),
/* OCTET STRING wrapper */
ASN1_GEN_STR("OCTWRAP", ASN1_GEN_FLAG_OCTWRAP),
/* SEQUENCE wrapper */
ASN1_GEN_STR("SEQWRAP", ASN1_GEN_FLAG_SEQWRAP),
/* SET wrapper */
ASN1_GEN_STR("SETWRAP", ASN1_GEN_FLAG_SETWRAP),
/* BIT STRING wrapper */
ASN1_GEN_STR("BITWRAP", ASN1_GEN_FLAG_BITWRAP),
ASN1_GEN_STR("FORM", ASN1_GEN_FLAG_FORMAT),
ASN1_GEN_STR("FORMAT", ASN1_GEN_FLAG_FORMAT),
};
if (len == -1)
len = strlen(tagstr);
tntmp = tnst;
for (i = 0; i < OSSL_NELEM(tnst); i++, tntmp++) {
if ((len == tntmp->len) && (strncmp(tntmp->strnam, tagstr, len) == 0))
return tntmp->tag;
}
return -1;
}
static ASN1_TYPE *asn1_str2type(const char *str, int format, int utype)
{
ASN1_TYPE *atmp = NULL;
CONF_VALUE vtmp;
unsigned char *rdata;
long rdlen;
int no_unused = 1;
if ((atmp = ASN1_TYPE_new()) == NULL) {
ASN1err(ASN1_F_ASN1_STR2TYPE, ERR_R_MALLOC_FAILURE);
return NULL;
}
if (!str)
str = "";
switch (utype) {
case V_ASN1_NULL:
if (str && *str) {
ASN1err(ASN1_F_ASN1_STR2TYPE, ASN1_R_ILLEGAL_NULL_VALUE);
goto bad_form;
}
break;
case V_ASN1_BOOLEAN:
if (format != ASN1_GEN_FORMAT_ASCII) {
ASN1err(ASN1_F_ASN1_STR2TYPE, ASN1_R_NOT_ASCII_FORMAT);
goto bad_form;
}
vtmp.name = NULL;
vtmp.section = NULL;
vtmp.value = (char *)str;
if (!X509V3_get_value_bool(&vtmp, &atmp->value.boolean)) {
ASN1err(ASN1_F_ASN1_STR2TYPE, ASN1_R_ILLEGAL_BOOLEAN);
goto bad_str;
}
break;
case V_ASN1_INTEGER:
case V_ASN1_ENUMERATED:
if (format != ASN1_GEN_FORMAT_ASCII) {
ASN1err(ASN1_F_ASN1_STR2TYPE, ASN1_R_INTEGER_NOT_ASCII_FORMAT);
goto bad_form;
}
if ((atmp->value.integer
= s2i_ASN1_INTEGER(NULL, str)) == NULL) {
ASN1err(ASN1_F_ASN1_STR2TYPE, ASN1_R_ILLEGAL_INTEGER);
goto bad_str;
}
break;
case V_ASN1_OBJECT:
if (format != ASN1_GEN_FORMAT_ASCII) {
ASN1err(ASN1_F_ASN1_STR2TYPE, ASN1_R_OBJECT_NOT_ASCII_FORMAT);
goto bad_form;
}
if ((atmp->value.object = OBJ_txt2obj(str, 0)) == NULL) {
ASN1err(ASN1_F_ASN1_STR2TYPE, ASN1_R_ILLEGAL_OBJECT);
goto bad_str;
}
break;
case V_ASN1_UTCTIME:
case V_ASN1_GENERALIZEDTIME:
if (format != ASN1_GEN_FORMAT_ASCII) {
ASN1err(ASN1_F_ASN1_STR2TYPE, ASN1_R_TIME_NOT_ASCII_FORMAT);
goto bad_form;
}
if ((atmp->value.asn1_string = ASN1_STRING_new()) == NULL) {
ASN1err(ASN1_F_ASN1_STR2TYPE, ERR_R_MALLOC_FAILURE);
goto bad_str;
}
if (!ASN1_STRING_set(atmp->value.asn1_string, str, -1)) {
ASN1err(ASN1_F_ASN1_STR2TYPE, ERR_R_MALLOC_FAILURE);
goto bad_str;
}
atmp->value.asn1_string->type = utype;
if (!ASN1_TIME_check(atmp->value.asn1_string)) {
ASN1err(ASN1_F_ASN1_STR2TYPE, ASN1_R_ILLEGAL_TIME_VALUE);
goto bad_str;
}
break;
case V_ASN1_BMPSTRING:
case V_ASN1_PRINTABLESTRING:
case V_ASN1_IA5STRING:
case V_ASN1_T61STRING:
case V_ASN1_UTF8STRING:
case V_ASN1_VISIBLESTRING:
case V_ASN1_UNIVERSALSTRING:
case V_ASN1_GENERALSTRING:
case V_ASN1_NUMERICSTRING:
if (format == ASN1_GEN_FORMAT_ASCII)
format = MBSTRING_ASC;
else if (format == ASN1_GEN_FORMAT_UTF8)
format = MBSTRING_UTF8;
else {
ASN1err(ASN1_F_ASN1_STR2TYPE, ASN1_R_ILLEGAL_FORMAT);
goto bad_form;
}
if (ASN1_mbstring_copy(&atmp->value.asn1_string, (unsigned char *)str,
-1, format, ASN1_tag2bit(utype)) <= 0) {
ASN1err(ASN1_F_ASN1_STR2TYPE, ERR_R_MALLOC_FAILURE);
goto bad_str;
}
break;
case V_ASN1_BIT_STRING:
case V_ASN1_OCTET_STRING:
if ((atmp->value.asn1_string = ASN1_STRING_new()) == NULL) {
ASN1err(ASN1_F_ASN1_STR2TYPE, ERR_R_MALLOC_FAILURE);
goto bad_form;
}
if (format == ASN1_GEN_FORMAT_HEX) {
if ((rdata = OPENSSL_hexstr2buf(str, &rdlen)) == NULL) {
ASN1err(ASN1_F_ASN1_STR2TYPE, ASN1_R_ILLEGAL_HEX);
goto bad_str;
}
atmp->value.asn1_string->data = rdata;
atmp->value.asn1_string->length = rdlen;
atmp->value.asn1_string->type = utype;
} else if (format == ASN1_GEN_FORMAT_ASCII)
ASN1_STRING_set(atmp->value.asn1_string, str, -1);
else if ((format == ASN1_GEN_FORMAT_BITLIST)
&& (utype == V_ASN1_BIT_STRING)) {
if (!CONF_parse_list
(str, ',', 1, bitstr_cb, atmp->value.bit_string)) {
ASN1err(ASN1_F_ASN1_STR2TYPE, ASN1_R_LIST_ERROR);
goto bad_str;
}
no_unused = 0;
} else {
ASN1err(ASN1_F_ASN1_STR2TYPE, ASN1_R_ILLEGAL_BITSTRING_FORMAT);
goto bad_form;
}
if ((utype == V_ASN1_BIT_STRING) && no_unused) {
atmp->value.asn1_string->flags
&= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07);
atmp->value.asn1_string->flags |= ASN1_STRING_FLAG_BITS_LEFT;
}
break;
default:
ASN1err(ASN1_F_ASN1_STR2TYPE, ASN1_R_UNSUPPORTED_TYPE);
goto bad_str;
}
atmp->type = utype;
return atmp;
bad_str:
ERR_add_error_data(2, "string=", str);
bad_form:
ASN1_TYPE_free(atmp);
return NULL;
}
static int bitstr_cb(const char *elem, int len, void *bitstr)
{
long bitnum;
char *eptr;
if (!elem)
return 0;
bitnum = strtoul(elem, &eptr, 10);
if (eptr && *eptr && (eptr != elem + len))
return 0;
if (bitnum < 0) {
ASN1err(ASN1_F_BITSTR_CB, ASN1_R_INVALID_NUMBER);
return 0;
}
if (!ASN1_BIT_STRING_set_bit(bitstr, bitnum, 1)) {
ASN1err(ASN1_F_BITSTR_CB, ERR_R_MALLOC_FAILURE);
return 0;
}
return 1;
}
static int mask_cb(const char *elem, int len, void *arg)
{
unsigned long *pmask = arg, tmpmask;
int tag;
if (elem == NULL)
return 0;
if ((len == 3) && (strncmp(elem, "DIR", 3) == 0)) {
*pmask |= B_ASN1_DIRECTORYSTRING;
return 1;
}
tag = asn1_str2tag(elem, len);
if (!tag || (tag & ASN1_GEN_FLAG))
return 0;
tmpmask = ASN1_tag2bit(tag);
if (!tmpmask)
return 0;
*pmask |= tmpmask;
return 1;
}
int ASN1_str2mask(const char *str, unsigned long *pmask)
{
*pmask = 0;
return CONF_parse_list(str, '|', 1, mask_cb, pmask);
}

View file

@ -0,0 +1,42 @@
/*
* Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <stdio.h>
#include "internal/cryptlib.h"
#include <openssl/asn1.h>
#include <openssl/asn1t.h>
#include <openssl/cms.h>
#include <openssl/dh.h>
#include <openssl/ocsp.h>
#include <openssl/pkcs7.h>
#include <openssl/pkcs12.h>
#include <openssl/rsa.h>
#include <openssl/x509v3.h>
#include "asn1_item_list.h"
const ASN1_ITEM *ASN1_ITEM_lookup(const char *name)
{
size_t i;
for (i = 0; i < OSSL_NELEM(asn1_item_list); i++) {
const ASN1_ITEM *it = ASN1_ITEM_ptr(asn1_item_list[i]);
if (strcmp(it->sname, name) == 0)
return it;
}
return NULL;
}
const ASN1_ITEM *ASN1_ITEM_get(size_t i)
{
if (i >= OSSL_NELEM(asn1_item_list))
return NULL;
return ASN1_ITEM_ptr(asn1_item_list[i]);
}

View file

@ -0,0 +1,178 @@
/*
* Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
static ASN1_ITEM_EXP *asn1_item_list[] = {
ASN1_ITEM_ref(ACCESS_DESCRIPTION),
#ifndef OPENSSL_NO_RFC3779
ASN1_ITEM_ref(ASIdOrRange),
ASN1_ITEM_ref(ASIdentifierChoice),
ASN1_ITEM_ref(ASIdentifiers),
#endif
ASN1_ITEM_ref(ASN1_ANY),
ASN1_ITEM_ref(ASN1_BIT_STRING),
ASN1_ITEM_ref(ASN1_BMPSTRING),
ASN1_ITEM_ref(ASN1_BOOLEAN),
ASN1_ITEM_ref(ASN1_ENUMERATED),
ASN1_ITEM_ref(ASN1_FBOOLEAN),
ASN1_ITEM_ref(ASN1_GENERALIZEDTIME),
ASN1_ITEM_ref(ASN1_GENERALSTRING),
ASN1_ITEM_ref(ASN1_IA5STRING),
ASN1_ITEM_ref(ASN1_INTEGER),
ASN1_ITEM_ref(ASN1_NULL),
ASN1_ITEM_ref(ASN1_OBJECT),
ASN1_ITEM_ref(ASN1_OCTET_STRING_NDEF),
ASN1_ITEM_ref(ASN1_OCTET_STRING),
ASN1_ITEM_ref(ASN1_PRINTABLESTRING),
ASN1_ITEM_ref(ASN1_PRINTABLE),
ASN1_ITEM_ref(ASN1_SEQUENCE_ANY),
ASN1_ITEM_ref(ASN1_SEQUENCE),
ASN1_ITEM_ref(ASN1_SET_ANY),
ASN1_ITEM_ref(ASN1_T61STRING),
ASN1_ITEM_ref(ASN1_TBOOLEAN),
ASN1_ITEM_ref(ASN1_TIME),
ASN1_ITEM_ref(ASN1_UNIVERSALSTRING),
ASN1_ITEM_ref(ASN1_UTCTIME),
ASN1_ITEM_ref(ASN1_UTF8STRING),
ASN1_ITEM_ref(ASN1_VISIBLESTRING),
#ifndef OPENSSL_NO_RFC3779
ASN1_ITEM_ref(ASRange),
#endif
ASN1_ITEM_ref(AUTHORITY_INFO_ACCESS),
ASN1_ITEM_ref(AUTHORITY_KEYID),
ASN1_ITEM_ref(BASIC_CONSTRAINTS),
ASN1_ITEM_ref(BIGNUM),
ASN1_ITEM_ref(CBIGNUM),
ASN1_ITEM_ref(CERTIFICATEPOLICIES),
#ifndef OPENSSL_NO_CMS
ASN1_ITEM_ref(CMS_ContentInfo),
ASN1_ITEM_ref(CMS_ReceiptRequest),
#endif
ASN1_ITEM_ref(CRL_DIST_POINTS),
#ifndef OPENSSL_NO_DH
ASN1_ITEM_ref(DHparams),
#endif
ASN1_ITEM_ref(DIRECTORYSTRING),
ASN1_ITEM_ref(DISPLAYTEXT),
ASN1_ITEM_ref(DIST_POINT_NAME),
ASN1_ITEM_ref(DIST_POINT),
#ifndef OPENSSL_NO_EC
ASN1_ITEM_ref(ECPARAMETERS),
ASN1_ITEM_ref(ECPKPARAMETERS),
#endif
ASN1_ITEM_ref(EDIPARTYNAME),
ASN1_ITEM_ref(EXTENDED_KEY_USAGE),
ASN1_ITEM_ref(GENERAL_NAMES),
ASN1_ITEM_ref(GENERAL_NAME),
ASN1_ITEM_ref(GENERAL_SUBTREE),
#ifndef OPENSSL_NO_RFC3779
ASN1_ITEM_ref(IPAddressChoice),
ASN1_ITEM_ref(IPAddressFamily),
ASN1_ITEM_ref(IPAddressOrRange),
ASN1_ITEM_ref(IPAddressRange),
#endif
ASN1_ITEM_ref(ISSUING_DIST_POINT),
#if OPENSSL_API_COMPAT < 0x10200000L
ASN1_ITEM_ref(LONG),
#endif
ASN1_ITEM_ref(NAME_CONSTRAINTS),
ASN1_ITEM_ref(NETSCAPE_CERT_SEQUENCE),
ASN1_ITEM_ref(NETSCAPE_SPKAC),
ASN1_ITEM_ref(NETSCAPE_SPKI),
ASN1_ITEM_ref(NOTICEREF),
#ifndef OPENSSL_NO_OCSP
ASN1_ITEM_ref(OCSP_BASICRESP),
ASN1_ITEM_ref(OCSP_CERTID),
ASN1_ITEM_ref(OCSP_CERTSTATUS),
ASN1_ITEM_ref(OCSP_CRLID),
ASN1_ITEM_ref(OCSP_ONEREQ),
ASN1_ITEM_ref(OCSP_REQINFO),
ASN1_ITEM_ref(OCSP_REQUEST),
ASN1_ITEM_ref(OCSP_RESPBYTES),
ASN1_ITEM_ref(OCSP_RESPDATA),
ASN1_ITEM_ref(OCSP_RESPID),
ASN1_ITEM_ref(OCSP_RESPONSE),
ASN1_ITEM_ref(OCSP_REVOKEDINFO),
ASN1_ITEM_ref(OCSP_SERVICELOC),
ASN1_ITEM_ref(OCSP_SIGNATURE),
ASN1_ITEM_ref(OCSP_SINGLERESP),
#endif
ASN1_ITEM_ref(OTHERNAME),
ASN1_ITEM_ref(PBE2PARAM),
ASN1_ITEM_ref(PBEPARAM),
ASN1_ITEM_ref(PBKDF2PARAM),
ASN1_ITEM_ref(PKCS12_AUTHSAFES),
ASN1_ITEM_ref(PKCS12_BAGS),
ASN1_ITEM_ref(PKCS12_MAC_DATA),
ASN1_ITEM_ref(PKCS12_SAFEBAGS),
ASN1_ITEM_ref(PKCS12_SAFEBAG),
ASN1_ITEM_ref(PKCS12),
ASN1_ITEM_ref(PKCS7_ATTR_SIGN),
ASN1_ITEM_ref(PKCS7_ATTR_VERIFY),
ASN1_ITEM_ref(PKCS7_DIGEST),
ASN1_ITEM_ref(PKCS7_ENCRYPT),
ASN1_ITEM_ref(PKCS7_ENC_CONTENT),
ASN1_ITEM_ref(PKCS7_ENVELOPE),
ASN1_ITEM_ref(PKCS7_ISSUER_AND_SERIAL),
ASN1_ITEM_ref(PKCS7_RECIP_INFO),
ASN1_ITEM_ref(PKCS7_SIGNED),
ASN1_ITEM_ref(PKCS7_SIGNER_INFO),
ASN1_ITEM_ref(PKCS7_SIGN_ENVELOPE),
ASN1_ITEM_ref(PKCS7),
ASN1_ITEM_ref(PKCS8_PRIV_KEY_INFO),
ASN1_ITEM_ref(PKEY_USAGE_PERIOD),
ASN1_ITEM_ref(POLICYINFO),
ASN1_ITEM_ref(POLICYQUALINFO),
ASN1_ITEM_ref(POLICY_CONSTRAINTS),
ASN1_ITEM_ref(POLICY_MAPPINGS),
ASN1_ITEM_ref(POLICY_MAPPING),
ASN1_ITEM_ref(PROXY_CERT_INFO_EXTENSION),
ASN1_ITEM_ref(PROXY_POLICY),
#ifndef OPENSSL_NO_RSA
ASN1_ITEM_ref(RSAPrivateKey),
ASN1_ITEM_ref(RSAPublicKey),
ASN1_ITEM_ref(RSA_OAEP_PARAMS),
ASN1_ITEM_ref(RSA_PSS_PARAMS),
#endif
#ifndef OPENSSL_NO_SCRYPT
ASN1_ITEM_ref(SCRYPT_PARAMS),
#endif
ASN1_ITEM_ref(SXNETID),
ASN1_ITEM_ref(SXNET),
ASN1_ITEM_ref(USERNOTICE),
ASN1_ITEM_ref(X509_ALGORS),
ASN1_ITEM_ref(X509_ALGOR),
ASN1_ITEM_ref(X509_ATTRIBUTE),
ASN1_ITEM_ref(X509_CERT_AUX),
ASN1_ITEM_ref(X509_CINF),
ASN1_ITEM_ref(X509_CRL_INFO),
ASN1_ITEM_ref(X509_CRL),
ASN1_ITEM_ref(X509_EXTENSIONS),
ASN1_ITEM_ref(X509_EXTENSION),
ASN1_ITEM_ref(X509_NAME_ENTRY),
ASN1_ITEM_ref(X509_NAME),
ASN1_ITEM_ref(X509_PUBKEY),
ASN1_ITEM_ref(X509_REQ_INFO),
ASN1_ITEM_ref(X509_REQ),
ASN1_ITEM_ref(X509_REVOKED),
ASN1_ITEM_ref(X509_SIG),
ASN1_ITEM_ref(X509_VAL),
ASN1_ITEM_ref(X509),
#if OPENSSL_API_COMPAT < 0x10200000L
ASN1_ITEM_ref(ZLONG),
#endif
ASN1_ITEM_ref(INT32),
ASN1_ITEM_ref(UINT32),
ASN1_ITEM_ref(ZINT32),
ASN1_ITEM_ref(ZUINT32),
ASN1_ITEM_ref(INT64),
ASN1_ITEM_ref(UINT64),
ASN1_ITEM_ref(ZINT64),
ASN1_ITEM_ref(ZUINT64),
};

View file

@ -0,0 +1,391 @@
/*
* Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <stdio.h>
#include <limits.h>
#include "internal/cryptlib.h"
#include <openssl/asn1.h>
#include "asn1_locl.h"
static int asn1_get_length(const unsigned char **pp, int *inf, long *rl,
long max);
static void asn1_put_length(unsigned char **pp, int length);
static int _asn1_check_infinite_end(const unsigned char **p, long len)
{
/*
* If there is 0 or 1 byte left, the length check should pick things up
*/
if (len <= 0)
return 1;
else if ((len >= 2) && ((*p)[0] == 0) && ((*p)[1] == 0)) {
(*p) += 2;
return 1;
}
return 0;
}
int ASN1_check_infinite_end(unsigned char **p, long len)
{
return _asn1_check_infinite_end((const unsigned char **)p, len);
}
int ASN1_const_check_infinite_end(const unsigned char **p, long len)
{
return _asn1_check_infinite_end(p, len);
}
int ASN1_get_object(const unsigned char **pp, long *plength, int *ptag,
int *pclass, long omax)
{
int i, ret;
long l;
const unsigned char *p = *pp;
int tag, xclass, inf;
long max = omax;
if (!max)
goto err;
ret = (*p & V_ASN1_CONSTRUCTED);
xclass = (*p & V_ASN1_PRIVATE);
i = *p & V_ASN1_PRIMITIVE_TAG;
if (i == V_ASN1_PRIMITIVE_TAG) { /* high-tag */
p++;
if (--max == 0)
goto err;
l = 0;
while (*p & 0x80) {
l <<= 7L;
l |= *(p++) & 0x7f;
if (--max == 0)
goto err;
if (l > (INT_MAX >> 7L))
goto err;
}
l <<= 7L;
l |= *(p++) & 0x7f;
tag = (int)l;
if (--max == 0)
goto err;
} else {
tag = i;
p++;
if (--max == 0)
goto err;
}
*ptag = tag;
*pclass = xclass;
if (!asn1_get_length(&p, &inf, plength, max))
goto err;
if (inf && !(ret & V_ASN1_CONSTRUCTED))
goto err;
if (*plength > (omax - (p - *pp))) {
ASN1err(ASN1_F_ASN1_GET_OBJECT, ASN1_R_TOO_LONG);
/*
* Set this so that even if things are not long enough the values are
* set correctly
*/
ret |= 0x80;
}
*pp = p;
return ret | inf;
err:
ASN1err(ASN1_F_ASN1_GET_OBJECT, ASN1_R_HEADER_TOO_LONG);
return 0x80;
}
/*
* Decode a length field.
* The short form is a single byte defining a length 0 - 127.
* The long form is a byte 0 - 127 with the top bit set and this indicates
* the number of following octets that contain the length. These octets
* are stored most significant digit first.
*/
static int asn1_get_length(const unsigned char **pp, int *inf, long *rl,
long max)
{
const unsigned char *p = *pp;
unsigned long ret = 0;
int i;
if (max-- < 1)
return 0;
if (*p == 0x80) {
*inf = 1;
p++;
} else {
*inf = 0;
i = *p & 0x7f;
if (*p++ & 0x80) {
if (max < i + 1)
return 0;
/* Skip leading zeroes */
while (i > 0 && *p == 0) {
p++;
i--;
}
if (i > (int)sizeof(long))
return 0;
while (i > 0) {
ret <<= 8;
ret |= *p++;
i--;
}
if (ret > LONG_MAX)
return 0;
} else
ret = i;
}
*pp = p;
*rl = (long)ret;
return 1;
}
/*
* class 0 is constructed constructed == 2 for indefinite length constructed
*/
void ASN1_put_object(unsigned char **pp, int constructed, int length, int tag,
int xclass)
{
unsigned char *p = *pp;
int i, ttag;
i = (constructed) ? V_ASN1_CONSTRUCTED : 0;
i |= (xclass & V_ASN1_PRIVATE);
if (tag < 31)
*(p++) = i | (tag & V_ASN1_PRIMITIVE_TAG);
else {
*(p++) = i | V_ASN1_PRIMITIVE_TAG;
for (i = 0, ttag = tag; ttag > 0; i++)
ttag >>= 7;
ttag = i;
while (i-- > 0) {
p[i] = tag & 0x7f;
if (i != (ttag - 1))
p[i] |= 0x80;
tag >>= 7;
}
p += ttag;
}
if (constructed == 2)
*(p++) = 0x80;
else
asn1_put_length(&p, length);
*pp = p;
}
int ASN1_put_eoc(unsigned char **pp)
{
unsigned char *p = *pp;
*p++ = 0;
*p++ = 0;
*pp = p;
return 2;
}
static void asn1_put_length(unsigned char **pp, int length)
{
unsigned char *p = *pp;
int i, l;
if (length <= 127)
*(p++) = (unsigned char)length;
else {
l = length;
for (i = 0; l > 0; i++)
l >>= 8;
*(p++) = i | 0x80;
l = i;
while (i-- > 0) {
p[i] = length & 0xff;
length >>= 8;
}
p += l;
}
*pp = p;
}
int ASN1_object_size(int constructed, int length, int tag)
{
int ret = 1;
if (length < 0)
return -1;
if (tag >= 31) {
while (tag > 0) {
tag >>= 7;
ret++;
}
}
if (constructed == 2) {
ret += 3;
} else {
ret++;
if (length > 127) {
int tmplen = length;
while (tmplen > 0) {
tmplen >>= 8;
ret++;
}
}
}
if (ret >= INT_MAX - length)
return -1;
return ret + length;
}
int ASN1_STRING_copy(ASN1_STRING *dst, const ASN1_STRING *str)
{
if (str == NULL)
return 0;
dst->type = str->type;
if (!ASN1_STRING_set(dst, str->data, str->length))
return 0;
/* Copy flags but preserve embed value */
dst->flags &= ASN1_STRING_FLAG_EMBED;
dst->flags |= str->flags & ~ASN1_STRING_FLAG_EMBED;
return 1;
}
ASN1_STRING *ASN1_STRING_dup(const ASN1_STRING *str)
{
ASN1_STRING *ret;
if (!str)
return NULL;
ret = ASN1_STRING_new();
if (ret == NULL)
return NULL;
if (!ASN1_STRING_copy(ret, str)) {
ASN1_STRING_free(ret);
return NULL;
}
return ret;
}
int ASN1_STRING_set(ASN1_STRING *str, const void *_data, int len)
{
unsigned char *c;
const char *data = _data;
if (len < 0) {
if (data == NULL)
return 0;
else
len = strlen(data);
}
if ((str->length <= len) || (str->data == NULL)) {
c = str->data;
str->data = OPENSSL_realloc(c, len + 1);
if (str->data == NULL) {
ASN1err(ASN1_F_ASN1_STRING_SET, ERR_R_MALLOC_FAILURE);
str->data = c;
return 0;
}
}
str->length = len;
if (data != NULL) {
memcpy(str->data, data, len);
/* an allowance for strings :-) */
str->data[len] = '\0';
}
return 1;
}
void ASN1_STRING_set0(ASN1_STRING *str, void *data, int len)
{
OPENSSL_free(str->data);
str->data = data;
str->length = len;
}
ASN1_STRING *ASN1_STRING_new(void)
{
return ASN1_STRING_type_new(V_ASN1_OCTET_STRING);
}
ASN1_STRING *ASN1_STRING_type_new(int type)
{
ASN1_STRING *ret;
ret = OPENSSL_zalloc(sizeof(*ret));
if (ret == NULL) {
ASN1err(ASN1_F_ASN1_STRING_TYPE_NEW, ERR_R_MALLOC_FAILURE);
return NULL;
}
ret->type = type;
return ret;
}
void asn1_string_embed_free(ASN1_STRING *a, int embed)
{
if (a == NULL)
return;
if (!(a->flags & ASN1_STRING_FLAG_NDEF))
OPENSSL_free(a->data);
if (embed == 0)
OPENSSL_free(a);
}
void ASN1_STRING_free(ASN1_STRING *a)
{
if (a == NULL)
return;
asn1_string_embed_free(a, a->flags & ASN1_STRING_FLAG_EMBED);
}
void ASN1_STRING_clear_free(ASN1_STRING *a)
{
if (a == NULL)
return;
if (a->data && !(a->flags & ASN1_STRING_FLAG_NDEF))
OPENSSL_cleanse(a->data, a->length);
ASN1_STRING_free(a);
}
int ASN1_STRING_cmp(const ASN1_STRING *a, const ASN1_STRING *b)
{
int i;
i = (a->length - b->length);
if (i == 0) {
i = memcmp(a->data, b->data, a->length);
if (i == 0)
return a->type - b->type;
else
return i;
} else
return i;
}
int ASN1_STRING_length(const ASN1_STRING *x)
{
return x->length;
}
void ASN1_STRING_length_set(ASN1_STRING *x, int len)
{
x->length = len;
}
int ASN1_STRING_type(const ASN1_STRING *x)
{
return x->type;
}
const unsigned char *ASN1_STRING_get0_data(const ASN1_STRING *x)
{
return x->data;
}
# if OPENSSL_API_COMPAT < 0x10100000L
unsigned char *ASN1_STRING_data(ASN1_STRING *x)
{
return x->data;
}
#endif

View file

@ -0,0 +1,83 @@
/*
* Copyright 2005-2017 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
/* Internal ASN1 structures and functions: not for application use */
int asn1_time_to_tm(struct tm *tm, const ASN1_TIME *d);
int asn1_utctime_to_tm(struct tm *tm, const ASN1_UTCTIME *d);
int asn1_generalizedtime_to_tm(struct tm *tm, const ASN1_GENERALIZEDTIME *d);
/* ASN1 scan context structure */
struct asn1_sctx_st {
/* The ASN1_ITEM associated with this field */
const ASN1_ITEM *it;
/* If ASN1_TEMPLATE associated with this field */
const ASN1_TEMPLATE *tt;
/* Various flags associated with field and context */
unsigned long flags;
/* If SEQUENCE OF or SET OF, field index */
int skidx;
/* ASN1 depth of field */
int depth;
/* Structure and field name */
const char *sname, *fname;
/* If a primitive type the type of underlying field */
int prim_type;
/* The field value itself */
ASN1_VALUE **field;
/* Callback to pass information to */
int (*scan_cb) (ASN1_SCTX *ctx);
/* Context specific application data */
void *app_data;
} /* ASN1_SCTX */ ;
typedef struct mime_param_st MIME_PARAM;
DEFINE_STACK_OF(MIME_PARAM)
typedef struct mime_header_st MIME_HEADER;
DEFINE_STACK_OF(MIME_HEADER)
void asn1_string_embed_free(ASN1_STRING *a, int embed);
int asn1_get_choice_selector(ASN1_VALUE **pval, const ASN1_ITEM *it);
int asn1_set_choice_selector(ASN1_VALUE **pval, int value,
const ASN1_ITEM *it);
ASN1_VALUE **asn1_get_field_ptr(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt);
const ASN1_TEMPLATE *asn1_do_adb(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt,
int nullerr);
int asn1_do_lock(ASN1_VALUE **pval, int op, const ASN1_ITEM *it);
void asn1_enc_init(ASN1_VALUE **pval, const ASN1_ITEM *it);
void asn1_enc_free(ASN1_VALUE **pval, const ASN1_ITEM *it);
int asn1_enc_restore(int *len, unsigned char **out, ASN1_VALUE **pval,
const ASN1_ITEM *it);
int asn1_enc_save(ASN1_VALUE **pval, const unsigned char *in, int inlen,
const ASN1_ITEM *it);
void asn1_item_embed_free(ASN1_VALUE **pval, const ASN1_ITEM *it, int embed);
void asn1_primitive_free(ASN1_VALUE **pval, const ASN1_ITEM *it, int embed);
void asn1_template_free(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt);
ASN1_OBJECT *c2i_ASN1_OBJECT(ASN1_OBJECT **a, const unsigned char **pp,
long length);
int i2c_ASN1_BIT_STRING(ASN1_BIT_STRING *a, unsigned char **pp);
ASN1_BIT_STRING *c2i_ASN1_BIT_STRING(ASN1_BIT_STRING **a,
const unsigned char **pp, long length);
int i2c_ASN1_INTEGER(ASN1_INTEGER *a, unsigned char **pp);
ASN1_INTEGER *c2i_ASN1_INTEGER(ASN1_INTEGER **a, const unsigned char **pp,
long length);
/* Internal functions used by x_int64.c */
int c2i_uint64_int(uint64_t *ret, int *neg, const unsigned char **pp, long len);
int i2c_uint64_int(unsigned char *p, uint64_t r, int neg);
ASN1_TIME *asn1_time_from_tm(ASN1_TIME *s, struct tm *ts, int type);

View file

@ -0,0 +1,375 @@
/*
* Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <stdio.h>
#include "internal/cryptlib.h"
#include <openssl/buffer.h>
#include <openssl/objects.h>
#include <openssl/asn1.h>
#ifndef ASN1_PARSE_MAXDEPTH
#define ASN1_PARSE_MAXDEPTH 128
#endif
static int asn1_print_info(BIO *bp, int tag, int xclass, int constructed,
int indent);
static int asn1_parse2(BIO *bp, const unsigned char **pp, long length,
int offset, int depth, int indent, int dump);
static int asn1_print_info(BIO *bp, int tag, int xclass, int constructed,
int indent)
{
static const char fmt[] = "%-18s";
char str[128];
const char *p;
if (constructed & V_ASN1_CONSTRUCTED)
p = "cons: ";
else
p = "prim: ";
if (BIO_write(bp, p, 6) < 6)
goto err;
BIO_indent(bp, indent, 128);
p = str;
if ((xclass & V_ASN1_PRIVATE) == V_ASN1_PRIVATE)
BIO_snprintf(str, sizeof(str), "priv [ %d ] ", tag);
else if ((xclass & V_ASN1_CONTEXT_SPECIFIC) == V_ASN1_CONTEXT_SPECIFIC)
BIO_snprintf(str, sizeof(str), "cont [ %d ]", tag);
else if ((xclass & V_ASN1_APPLICATION) == V_ASN1_APPLICATION)
BIO_snprintf(str, sizeof(str), "appl [ %d ]", tag);
else if (tag > 30)
BIO_snprintf(str, sizeof(str), "<ASN1 %d>", tag);
else
p = ASN1_tag2str(tag);
if (BIO_printf(bp, fmt, p) <= 0)
goto err;
return 1;
err:
return 0;
}
int ASN1_parse(BIO *bp, const unsigned char *pp, long len, int indent)
{
return asn1_parse2(bp, &pp, len, 0, 0, indent, 0);
}
int ASN1_parse_dump(BIO *bp, const unsigned char *pp, long len, int indent,
int dump)
{
return asn1_parse2(bp, &pp, len, 0, 0, indent, dump);
}
static int asn1_parse2(BIO *bp, const unsigned char **pp, long length,
int offset, int depth, int indent, int dump)
{
const unsigned char *p, *ep, *tot, *op, *opp;
long len;
int tag, xclass, ret = 0;
int nl, hl, j, r;
ASN1_OBJECT *o = NULL;
ASN1_OCTET_STRING *os = NULL;
/* ASN1_BMPSTRING *bmp=NULL; */
int dump_indent, dump_cont = 0;
if (depth > ASN1_PARSE_MAXDEPTH) {
BIO_puts(bp, "BAD RECURSION DEPTH\n");
return 0;
}
dump_indent = 6; /* Because we know BIO_dump_indent() */
p = *pp;
tot = p + length;
while (length > 0) {
op = p;
j = ASN1_get_object(&p, &len, &tag, &xclass, length);
if (j & 0x80) {
if (BIO_write(bp, "Error in encoding\n", 18) <= 0)
goto end;
ret = 0;
goto end;
}
hl = (p - op);
length -= hl;
/*
* if j == 0x21 it is a constructed indefinite length object
*/
if (BIO_printf(bp, "%5ld:", (long)offset + (long)(op - *pp))
<= 0)
goto end;
if (j != (V_ASN1_CONSTRUCTED | 1)) {
if (BIO_printf(bp, "d=%-2d hl=%ld l=%4ld ",
depth, (long)hl, len) <= 0)
goto end;
} else {
if (BIO_printf(bp, "d=%-2d hl=%ld l=inf ", depth, (long)hl) <= 0)
goto end;
}
if (!asn1_print_info(bp, tag, xclass, j, (indent) ? depth : 0))
goto end;
if (j & V_ASN1_CONSTRUCTED) {
const unsigned char *sp = p;
ep = p + len;
if (BIO_write(bp, "\n", 1) <= 0)
goto end;
if (len > length) {
BIO_printf(bp, "length is greater than %ld\n", length);
ret = 0;
goto end;
}
if ((j == 0x21) && (len == 0)) {
for (;;) {
r = asn1_parse2(bp, &p, (long)(tot - p),
offset + (p - *pp), depth + 1,
indent, dump);
if (r == 0) {
ret = 0;
goto end;
}
if ((r == 2) || (p >= tot)) {
len = p - sp;
break;
}
}
} else {
long tmp = len;
while (p < ep) {
sp = p;
r = asn1_parse2(bp, &p, tmp,
offset + (p - *pp), depth + 1,
indent, dump);
if (r == 0) {
ret = 0;
goto end;
}
tmp -= p - sp;
}
}
} else if (xclass != 0) {
p += len;
if (BIO_write(bp, "\n", 1) <= 0)
goto end;
} else {
nl = 0;
if ((tag == V_ASN1_PRINTABLESTRING) ||
(tag == V_ASN1_T61STRING) ||
(tag == V_ASN1_IA5STRING) ||
(tag == V_ASN1_VISIBLESTRING) ||
(tag == V_ASN1_NUMERICSTRING) ||
(tag == V_ASN1_UTF8STRING) ||
(tag == V_ASN1_UTCTIME) || (tag == V_ASN1_GENERALIZEDTIME)) {
if (BIO_write(bp, ":", 1) <= 0)
goto end;
if ((len > 0) && BIO_write(bp, (const char *)p, (int)len)
!= (int)len)
goto end;
} else if (tag == V_ASN1_OBJECT) {
opp = op;
if (d2i_ASN1_OBJECT(&o, &opp, len + hl) != NULL) {
if (BIO_write(bp, ":", 1) <= 0)
goto end;
i2a_ASN1_OBJECT(bp, o);
} else {
if (BIO_puts(bp, ":BAD OBJECT") <= 0)
goto end;
dump_cont = 1;
}
} else if (tag == V_ASN1_BOOLEAN) {
if (len != 1) {
if (BIO_puts(bp, ":BAD BOOLEAN") <= 0)
goto end;
dump_cont = 1;
}
if (len > 0)
BIO_printf(bp, ":%u", p[0]);
} else if (tag == V_ASN1_BMPSTRING) {
/* do the BMP thang */
} else if (tag == V_ASN1_OCTET_STRING) {
int i, printable = 1;
opp = op;
os = d2i_ASN1_OCTET_STRING(NULL, &opp, len + hl);
if (os != NULL && os->length > 0) {
opp = os->data;
/*
* testing whether the octet string is printable
*/
for (i = 0; i < os->length; i++) {
if (((opp[i] < ' ') &&
(opp[i] != '\n') &&
(opp[i] != '\r') &&
(opp[i] != '\t')) || (opp[i] > '~')) {
printable = 0;
break;
}
}
if (printable)
/* printable string */
{
if (BIO_write(bp, ":", 1) <= 0)
goto end;
if (BIO_write(bp, (const char *)opp, os->length) <= 0)
goto end;
} else if (!dump)
/*
* not printable => print octet string as hex dump
*/
{
if (BIO_write(bp, "[HEX DUMP]:", 11) <= 0)
goto end;
for (i = 0; i < os->length; i++) {
if (BIO_printf(bp, "%02X", opp[i]) <= 0)
goto end;
}
} else
/* print the normal dump */
{
if (!nl) {
if (BIO_write(bp, "\n", 1) <= 0)
goto end;
}
if (BIO_dump_indent(bp,
(const char *)opp,
((dump == -1 || dump >
os->
length) ? os->length : dump),
dump_indent) <= 0)
goto end;
nl = 1;
}
}
ASN1_OCTET_STRING_free(os);
os = NULL;
} else if (tag == V_ASN1_INTEGER) {
ASN1_INTEGER *bs;
int i;
opp = op;
bs = d2i_ASN1_INTEGER(NULL, &opp, len + hl);
if (bs != NULL) {
if (BIO_write(bp, ":", 1) <= 0)
goto end;
if (bs->type == V_ASN1_NEG_INTEGER)
if (BIO_write(bp, "-", 1) <= 0)
goto end;
for (i = 0; i < bs->length; i++) {
if (BIO_printf(bp, "%02X", bs->data[i]) <= 0)
goto end;
}
if (bs->length == 0) {
if (BIO_write(bp, "00", 2) <= 0)
goto end;
}
} else {
if (BIO_puts(bp, ":BAD INTEGER") <= 0)
goto end;
dump_cont = 1;
}
ASN1_INTEGER_free(bs);
} else if (tag == V_ASN1_ENUMERATED) {
ASN1_ENUMERATED *bs;
int i;
opp = op;
bs = d2i_ASN1_ENUMERATED(NULL, &opp, len + hl);
if (bs != NULL) {
if (BIO_write(bp, ":", 1) <= 0)
goto end;
if (bs->type == V_ASN1_NEG_ENUMERATED)
if (BIO_write(bp, "-", 1) <= 0)
goto end;
for (i = 0; i < bs->length; i++) {
if (BIO_printf(bp, "%02X", bs->data[i]) <= 0)
goto end;
}
if (bs->length == 0) {
if (BIO_write(bp, "00", 2) <= 0)
goto end;
}
} else {
if (BIO_puts(bp, ":BAD ENUMERATED") <= 0)
goto end;
dump_cont = 1;
}
ASN1_ENUMERATED_free(bs);
} else if (len > 0 && dump) {
if (!nl) {
if (BIO_write(bp, "\n", 1) <= 0)
goto end;
}
if (BIO_dump_indent(bp, (const char *)p,
((dump == -1 || dump > len) ? len : dump),
dump_indent) <= 0)
goto end;
nl = 1;
}
if (dump_cont) {
int i;
const unsigned char *tmp = op + hl;
if (BIO_puts(bp, ":[") <= 0)
goto end;
for (i = 0; i < len; i++) {
if (BIO_printf(bp, "%02X", tmp[i]) <= 0)
goto end;
}
if (BIO_puts(bp, "]") <= 0)
goto end;
}
if (!nl) {
if (BIO_write(bp, "\n", 1) <= 0)
goto end;
}
p += len;
if ((tag == V_ASN1_EOC) && (xclass == 0)) {
ret = 2; /* End of sequence */
goto end;
}
}
length -= len;
}
ret = 1;
end:
ASN1_OBJECT_free(o);
ASN1_OCTET_STRING_free(os);
*pp = p;
return ret;
}
const char *ASN1_tag2str(int tag)
{
static const char *const tag2str[] = {
/* 0-4 */
"EOC", "BOOLEAN", "INTEGER", "BIT STRING", "OCTET STRING",
/* 5-9 */
"NULL", "OBJECT", "OBJECT DESCRIPTOR", "EXTERNAL", "REAL",
/* 10-13 */
"ENUMERATED", "<ASN1 11>", "UTF8STRING", "<ASN1 13>",
/* 15-17 */
"<ASN1 14>", "<ASN1 15>", "SEQUENCE", "SET",
/* 18-20 */
"NUMERICSTRING", "PRINTABLESTRING", "T61STRING",
/* 21-24 */
"VIDEOTEXSTRING", "IA5STRING", "UTCTIME", "GENERALIZEDTIME",
/* 25-27 */
"GRAPHICSTRING", "VISIBLESTRING", "GENERALSTRING",
/* 28-30 */
"UNIVERSALSTRING", "<ASN1 29>", "BMPSTRING"
};
if ((tag == V_ASN1_NEG_INTEGER) || (tag == V_ASN1_NEG_ENUMERATED))
tag &= ~0x100;
if (tag < 0 || tag > 30)
return "(unknown)";
return tag2str[tag];
}

View file

@ -0,0 +1,963 @@
/*
* Copyright 2008-2018 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <stdio.h>
#include "internal/ctype.h"
#include "internal/cryptlib.h"
#include <openssl/rand.h>
#include <openssl/x509.h>
#include <openssl/asn1.h>
#include <openssl/asn1t.h>
#include "internal/evp_int.h"
#include "internal/bio.h"
#include "asn1_locl.h"
/*
* Generalised MIME like utilities for streaming ASN1. Although many have a
* PKCS7/CMS like flavour others are more general purpose.
*/
/*
* MIME format structures Note that all are translated to lower case apart
* from parameter values. Quotes are stripped off
*/
struct mime_param_st {
char *param_name; /* Param name e.g. "micalg" */
char *param_value; /* Param value e.g. "sha1" */
};
struct mime_header_st {
char *name; /* Name of line e.g. "content-type" */
char *value; /* Value of line e.g. "text/plain" */
STACK_OF(MIME_PARAM) *params; /* Zero or more parameters */
};
static int asn1_output_data(BIO *out, BIO *data, ASN1_VALUE *val, int flags,
const ASN1_ITEM *it);
static char *strip_ends(char *name);
static char *strip_start(char *name);
static char *strip_end(char *name);
static MIME_HEADER *mime_hdr_new(const char *name, const char *value);
static int mime_hdr_addparam(MIME_HEADER *mhdr, const char *name, const char *value);
static STACK_OF(MIME_HEADER) *mime_parse_hdr(BIO *bio);
static int mime_hdr_cmp(const MIME_HEADER *const *a,
const MIME_HEADER *const *b);
static int mime_param_cmp(const MIME_PARAM *const *a,
const MIME_PARAM *const *b);
static void mime_param_free(MIME_PARAM *param);
static int mime_bound_check(char *line, int linelen, const char *bound, int blen);
static int multi_split(BIO *bio, const char *bound, STACK_OF(BIO) **ret);
static int strip_eol(char *linebuf, int *plen, int flags);
static MIME_HEADER *mime_hdr_find(STACK_OF(MIME_HEADER) *hdrs, const char *name);
static MIME_PARAM *mime_param_find(MIME_HEADER *hdr, const char *name);
static void mime_hdr_free(MIME_HEADER *hdr);
#define MAX_SMLEN 1024
#define mime_debug(x) /* x */
/* Output an ASN1 structure in BER format streaming if necessary */
int i2d_ASN1_bio_stream(BIO *out, ASN1_VALUE *val, BIO *in, int flags,
const ASN1_ITEM *it)
{
/* If streaming create stream BIO and copy all content through it */
if (flags & SMIME_STREAM) {
BIO *bio, *tbio;
bio = BIO_new_NDEF(out, val, it);
if (!bio) {
ASN1err(ASN1_F_I2D_ASN1_BIO_STREAM, ERR_R_MALLOC_FAILURE);
return 0;
}
SMIME_crlf_copy(in, bio, flags);
(void)BIO_flush(bio);
/* Free up successive BIOs until we hit the old output BIO */
do {
tbio = BIO_pop(bio);
BIO_free(bio);
bio = tbio;
} while (bio != out);
}
/*
* else just write out ASN1 structure which will have all content stored
* internally
*/
else
ASN1_item_i2d_bio(it, out, val);
return 1;
}
/* Base 64 read and write of ASN1 structure */
static int B64_write_ASN1(BIO *out, ASN1_VALUE *val, BIO *in, int flags,
const ASN1_ITEM *it)
{
BIO *b64;
int r;
b64 = BIO_new(BIO_f_base64());
if (b64 == NULL) {
ASN1err(ASN1_F_B64_WRITE_ASN1, ERR_R_MALLOC_FAILURE);
return 0;
}
/*
* prepend the b64 BIO so all data is base64 encoded.
*/
out = BIO_push(b64, out);
r = i2d_ASN1_bio_stream(out, val, in, flags, it);
(void)BIO_flush(out);
BIO_pop(out);
BIO_free(b64);
return r;
}
/* Streaming ASN1 PEM write */
int PEM_write_bio_ASN1_stream(BIO *out, ASN1_VALUE *val, BIO *in, int flags,
const char *hdr, const ASN1_ITEM *it)
{
int r;
BIO_printf(out, "-----BEGIN %s-----\n", hdr);
r = B64_write_ASN1(out, val, in, flags, it);
BIO_printf(out, "-----END %s-----\n", hdr);
return r;
}
static ASN1_VALUE *b64_read_asn1(BIO *bio, const ASN1_ITEM *it)
{
BIO *b64;
ASN1_VALUE *val;
if ((b64 = BIO_new(BIO_f_base64())) == NULL) {
ASN1err(ASN1_F_B64_READ_ASN1, ERR_R_MALLOC_FAILURE);
return 0;
}
bio = BIO_push(b64, bio);
val = ASN1_item_d2i_bio(it, bio, NULL);
if (!val)
ASN1err(ASN1_F_B64_READ_ASN1, ASN1_R_DECODE_ERROR);
(void)BIO_flush(bio);
BIO_pop(bio);
BIO_free(b64);
return val;
}
/* Generate the MIME "micalg" parameter from RFC3851, RFC4490 */
static int asn1_write_micalg(BIO *out, STACK_OF(X509_ALGOR) *mdalgs)
{
const EVP_MD *md;
int i, have_unknown = 0, write_comma, ret = 0, md_nid;
have_unknown = 0;
write_comma = 0;
for (i = 0; i < sk_X509_ALGOR_num(mdalgs); i++) {
if (write_comma)
BIO_write(out, ",", 1);
write_comma = 1;
md_nid = OBJ_obj2nid(sk_X509_ALGOR_value(mdalgs, i)->algorithm);
md = EVP_get_digestbynid(md_nid);
if (md && md->md_ctrl) {
int rv;
char *micstr;
rv = md->md_ctrl(NULL, EVP_MD_CTRL_MICALG, 0, &micstr);
if (rv > 0) {
BIO_puts(out, micstr);
OPENSSL_free(micstr);
continue;
}
if (rv != -2)
goto err;
}
switch (md_nid) {
case NID_sha1:
BIO_puts(out, "sha1");
break;
case NID_md5:
BIO_puts(out, "md5");
break;
case NID_sha256:
BIO_puts(out, "sha-256");
break;
case NID_sha384:
BIO_puts(out, "sha-384");
break;
case NID_sha512:
BIO_puts(out, "sha-512");
break;
case NID_id_GostR3411_94:
BIO_puts(out, "gostr3411-94");
goto err;
default:
if (have_unknown)
write_comma = 0;
else {
BIO_puts(out, "unknown");
have_unknown = 1;
}
break;
}
}
ret = 1;
err:
return ret;
}
/* SMIME sender */
int SMIME_write_ASN1(BIO *bio, ASN1_VALUE *val, BIO *data, int flags,
int ctype_nid, int econt_nid,
STACK_OF(X509_ALGOR) *mdalgs, const ASN1_ITEM *it)
{
char bound[33], c;
int i;
const char *mime_prefix, *mime_eol, *cname = "smime.p7m";
const char *msg_type = NULL;
if (flags & SMIME_OLDMIME)
mime_prefix = "application/x-pkcs7-";
else
mime_prefix = "application/pkcs7-";
if (flags & SMIME_CRLFEOL)
mime_eol = "\r\n";
else
mime_eol = "\n";
if ((flags & SMIME_DETACHED) && data) {
/* We want multipart/signed */
/* Generate a random boundary */
if (RAND_bytes((unsigned char *)bound, 32) <= 0)
return 0;
for (i = 0; i < 32; i++) {
c = bound[i] & 0xf;
if (c < 10)
c += '0';
else
c += 'A' - 10;
bound[i] = c;
}
bound[32] = 0;
BIO_printf(bio, "MIME-Version: 1.0%s", mime_eol);
BIO_printf(bio, "Content-Type: multipart/signed;");
BIO_printf(bio, " protocol=\"%ssignature\";", mime_prefix);
BIO_puts(bio, " micalg=\"");
asn1_write_micalg(bio, mdalgs);
BIO_printf(bio, "\"; boundary=\"----%s\"%s%s",
bound, mime_eol, mime_eol);
BIO_printf(bio, "This is an S/MIME signed message%s%s",
mime_eol, mime_eol);
/* Now write out the first part */
BIO_printf(bio, "------%s%s", bound, mime_eol);
if (!asn1_output_data(bio, data, val, flags, it))
return 0;
BIO_printf(bio, "%s------%s%s", mime_eol, bound, mime_eol);
/* Headers for signature */
BIO_printf(bio, "Content-Type: %ssignature;", mime_prefix);
BIO_printf(bio, " name=\"smime.p7s\"%s", mime_eol);
BIO_printf(bio, "Content-Transfer-Encoding: base64%s", mime_eol);
BIO_printf(bio, "Content-Disposition: attachment;");
BIO_printf(bio, " filename=\"smime.p7s\"%s%s", mime_eol, mime_eol);
B64_write_ASN1(bio, val, NULL, 0, it);
BIO_printf(bio, "%s------%s--%s%s", mime_eol, bound,
mime_eol, mime_eol);
return 1;
}
/* Determine smime-type header */
if (ctype_nid == NID_pkcs7_enveloped)
msg_type = "enveloped-data";
else if (ctype_nid == NID_pkcs7_signed) {
if (econt_nid == NID_id_smime_ct_receipt)
msg_type = "signed-receipt";
else if (sk_X509_ALGOR_num(mdalgs) >= 0)
msg_type = "signed-data";
else
msg_type = "certs-only";
} else if (ctype_nid == NID_id_smime_ct_compressedData) {
msg_type = "compressed-data";
cname = "smime.p7z";
}
/* MIME headers */
BIO_printf(bio, "MIME-Version: 1.0%s", mime_eol);
BIO_printf(bio, "Content-Disposition: attachment;");
BIO_printf(bio, " filename=\"%s\"%s", cname, mime_eol);
BIO_printf(bio, "Content-Type: %smime;", mime_prefix);
if (msg_type)
BIO_printf(bio, " smime-type=%s;", msg_type);
BIO_printf(bio, " name=\"%s\"%s", cname, mime_eol);
BIO_printf(bio, "Content-Transfer-Encoding: base64%s%s",
mime_eol, mime_eol);
if (!B64_write_ASN1(bio, val, data, flags, it))
return 0;
BIO_printf(bio, "%s", mime_eol);
return 1;
}
/* Handle output of ASN1 data */
static int asn1_output_data(BIO *out, BIO *data, ASN1_VALUE *val, int flags,
const ASN1_ITEM *it)
{
BIO *tmpbio;
const ASN1_AUX *aux = it->funcs;
ASN1_STREAM_ARG sarg;
int rv = 1;
/*
* If data is not detached or resigning then the output BIO is already
* set up to finalise when it is written through.
*/
if (!(flags & SMIME_DETACHED) || (flags & PKCS7_REUSE_DIGEST)) {
SMIME_crlf_copy(data, out, flags);
return 1;
}
if (!aux || !aux->asn1_cb) {
ASN1err(ASN1_F_ASN1_OUTPUT_DATA, ASN1_R_STREAMING_NOT_SUPPORTED);
return 0;
}
sarg.out = out;
sarg.ndef_bio = NULL;
sarg.boundary = NULL;
/* Let ASN1 code prepend any needed BIOs */
if (aux->asn1_cb(ASN1_OP_DETACHED_PRE, &val, it, &sarg) <= 0)
return 0;
/* Copy data across, passing through filter BIOs for processing */
SMIME_crlf_copy(data, sarg.ndef_bio, flags);
/* Finalize structure */
if (aux->asn1_cb(ASN1_OP_DETACHED_POST, &val, it, &sarg) <= 0)
rv = 0;
/* Now remove any digests prepended to the BIO */
while (sarg.ndef_bio != out) {
tmpbio = BIO_pop(sarg.ndef_bio);
BIO_free(sarg.ndef_bio);
sarg.ndef_bio = tmpbio;
}
return rv;
}
/*
* SMIME reader: handle multipart/signed and opaque signing. in multipart
* case the content is placed in a memory BIO pointed to by "bcont". In
* opaque this is set to NULL
*/
ASN1_VALUE *SMIME_read_ASN1(BIO *bio, BIO **bcont, const ASN1_ITEM *it)
{
BIO *asnin;
STACK_OF(MIME_HEADER) *headers = NULL;
STACK_OF(BIO) *parts = NULL;
MIME_HEADER *hdr;
MIME_PARAM *prm;
ASN1_VALUE *val;
int ret;
if (bcont)
*bcont = NULL;
if ((headers = mime_parse_hdr(bio)) == NULL) {
ASN1err(ASN1_F_SMIME_READ_ASN1, ASN1_R_MIME_PARSE_ERROR);
return NULL;
}
if ((hdr = mime_hdr_find(headers, "content-type")) == NULL
|| hdr->value == NULL) {
sk_MIME_HEADER_pop_free(headers, mime_hdr_free);
ASN1err(ASN1_F_SMIME_READ_ASN1, ASN1_R_NO_CONTENT_TYPE);
return NULL;
}
/* Handle multipart/signed */
if (strcmp(hdr->value, "multipart/signed") == 0) {
/* Split into two parts */
prm = mime_param_find(hdr, "boundary");
if (!prm || !prm->param_value) {
sk_MIME_HEADER_pop_free(headers, mime_hdr_free);
ASN1err(ASN1_F_SMIME_READ_ASN1, ASN1_R_NO_MULTIPART_BOUNDARY);
return NULL;
}
ret = multi_split(bio, prm->param_value, &parts);
sk_MIME_HEADER_pop_free(headers, mime_hdr_free);
if (!ret || (sk_BIO_num(parts) != 2)) {
ASN1err(ASN1_F_SMIME_READ_ASN1, ASN1_R_NO_MULTIPART_BODY_FAILURE);
sk_BIO_pop_free(parts, BIO_vfree);
return NULL;
}
/* Parse the signature piece */
asnin = sk_BIO_value(parts, 1);
if ((headers = mime_parse_hdr(asnin)) == NULL) {
ASN1err(ASN1_F_SMIME_READ_ASN1, ASN1_R_MIME_SIG_PARSE_ERROR);
sk_BIO_pop_free(parts, BIO_vfree);
return NULL;
}
/* Get content type */
if ((hdr = mime_hdr_find(headers, "content-type")) == NULL
|| hdr->value == NULL) {
sk_MIME_HEADER_pop_free(headers, mime_hdr_free);
ASN1err(ASN1_F_SMIME_READ_ASN1, ASN1_R_NO_SIG_CONTENT_TYPE);
sk_BIO_pop_free(parts, BIO_vfree);
return NULL;
}
if (strcmp(hdr->value, "application/x-pkcs7-signature") &&
strcmp(hdr->value, "application/pkcs7-signature")) {
ASN1err(ASN1_F_SMIME_READ_ASN1, ASN1_R_SIG_INVALID_MIME_TYPE);
ERR_add_error_data(2, "type: ", hdr->value);
sk_MIME_HEADER_pop_free(headers, mime_hdr_free);
sk_BIO_pop_free(parts, BIO_vfree);
return NULL;
}
sk_MIME_HEADER_pop_free(headers, mime_hdr_free);
/* Read in ASN1 */
if ((val = b64_read_asn1(asnin, it)) == NULL) {
ASN1err(ASN1_F_SMIME_READ_ASN1, ASN1_R_ASN1_SIG_PARSE_ERROR);
sk_BIO_pop_free(parts, BIO_vfree);
return NULL;
}
if (bcont) {
*bcont = sk_BIO_value(parts, 0);
BIO_free(asnin);
sk_BIO_free(parts);
} else
sk_BIO_pop_free(parts, BIO_vfree);
return val;
}
/* OK, if not multipart/signed try opaque signature */
if (strcmp(hdr->value, "application/x-pkcs7-mime") &&
strcmp(hdr->value, "application/pkcs7-mime")) {
ASN1err(ASN1_F_SMIME_READ_ASN1, ASN1_R_INVALID_MIME_TYPE);
ERR_add_error_data(2, "type: ", hdr->value);
sk_MIME_HEADER_pop_free(headers, mime_hdr_free);
return NULL;
}
sk_MIME_HEADER_pop_free(headers, mime_hdr_free);
if ((val = b64_read_asn1(bio, it)) == NULL) {
ASN1err(ASN1_F_SMIME_READ_ASN1, ASN1_R_ASN1_PARSE_ERROR);
return NULL;
}
return val;
}
/* Copy text from one BIO to another making the output CRLF at EOL */
int SMIME_crlf_copy(BIO *in, BIO *out, int flags)
{
BIO *bf;
char eol;
int len;
char linebuf[MAX_SMLEN];
/*
* Buffer output so we don't write one line at a time. This is useful
* when streaming as we don't end up with one OCTET STRING per line.
*/
bf = BIO_new(BIO_f_buffer());
if (bf == NULL)
return 0;
out = BIO_push(bf, out);
if (flags & SMIME_BINARY) {
while ((len = BIO_read(in, linebuf, MAX_SMLEN)) > 0)
BIO_write(out, linebuf, len);
} else {
int eolcnt = 0;
if (flags & SMIME_TEXT)
BIO_printf(out, "Content-Type: text/plain\r\n\r\n");
while ((len = BIO_gets(in, linebuf, MAX_SMLEN)) > 0) {
eol = strip_eol(linebuf, &len, flags);
if (len) {
/* Not EOF: write out all CRLF */
if (flags & SMIME_ASCIICRLF) {
int i;
for (i = 0; i < eolcnt; i++)
BIO_write(out, "\r\n", 2);
eolcnt = 0;
}
BIO_write(out, linebuf, len);
if (eol)
BIO_write(out, "\r\n", 2);
} else if (flags & SMIME_ASCIICRLF)
eolcnt++;
else if (eol)
BIO_write(out, "\r\n", 2);
}
}
(void)BIO_flush(out);
BIO_pop(out);
BIO_free(bf);
return 1;
}
/* Strip off headers if they are text/plain */
int SMIME_text(BIO *in, BIO *out)
{
char iobuf[4096];
int len;
STACK_OF(MIME_HEADER) *headers;
MIME_HEADER *hdr;
if ((headers = mime_parse_hdr(in)) == NULL) {
ASN1err(ASN1_F_SMIME_TEXT, ASN1_R_MIME_PARSE_ERROR);
return 0;
}
if ((hdr = mime_hdr_find(headers, "content-type")) == NULL
|| hdr->value == NULL) {
ASN1err(ASN1_F_SMIME_TEXT, ASN1_R_MIME_NO_CONTENT_TYPE);
sk_MIME_HEADER_pop_free(headers, mime_hdr_free);
return 0;
}
if (strcmp(hdr->value, "text/plain")) {
ASN1err(ASN1_F_SMIME_TEXT, ASN1_R_INVALID_MIME_TYPE);
ERR_add_error_data(2, "type: ", hdr->value);
sk_MIME_HEADER_pop_free(headers, mime_hdr_free);
return 0;
}
sk_MIME_HEADER_pop_free(headers, mime_hdr_free);
while ((len = BIO_read(in, iobuf, sizeof(iobuf))) > 0)
BIO_write(out, iobuf, len);
if (len < 0)
return 0;
return 1;
}
/*
* Split a multipart/XXX message body into component parts: result is
* canonical parts in a STACK of bios
*/
static int multi_split(BIO *bio, const char *bound, STACK_OF(BIO) **ret)
{
char linebuf[MAX_SMLEN];
int len, blen;
int eol = 0, next_eol = 0;
BIO *bpart = NULL;
STACK_OF(BIO) *parts;
char state, part, first;
blen = strlen(bound);
part = 0;
state = 0;
first = 1;
parts = sk_BIO_new_null();
*ret = parts;
if (*ret == NULL)
return 0;
while ((len = BIO_gets(bio, linebuf, MAX_SMLEN)) > 0) {
state = mime_bound_check(linebuf, len, bound, blen);
if (state == 1) {
first = 1;
part++;
} else if (state == 2) {
if (!sk_BIO_push(parts, bpart)) {
BIO_free(bpart);
return 0;
}
return 1;
} else if (part) {
/* Strip CR+LF from linebuf */
next_eol = strip_eol(linebuf, &len, 0);
if (first) {
first = 0;
if (bpart)
if (!sk_BIO_push(parts, bpart)) {
BIO_free(bpart);
return 0;
}
bpart = BIO_new(BIO_s_mem());
if (bpart == NULL)
return 0;
BIO_set_mem_eof_return(bpart, 0);
} else if (eol)
BIO_write(bpart, "\r\n", 2);
eol = next_eol;
if (len)
BIO_write(bpart, linebuf, len);
}
}
BIO_free(bpart);
return 0;
}
/* This is the big one: parse MIME header lines up to message body */
#define MIME_INVALID 0
#define MIME_START 1
#define MIME_TYPE 2
#define MIME_NAME 3
#define MIME_VALUE 4
#define MIME_QUOTE 5
#define MIME_COMMENT 6
static STACK_OF(MIME_HEADER) *mime_parse_hdr(BIO *bio)
{
char *p, *q, c;
char *ntmp;
char linebuf[MAX_SMLEN];
MIME_HEADER *mhdr = NULL, *new_hdr = NULL;
STACK_OF(MIME_HEADER) *headers;
int len, state, save_state = 0;
headers = sk_MIME_HEADER_new(mime_hdr_cmp);
if (headers == NULL)
return NULL;
while ((len = BIO_gets(bio, linebuf, MAX_SMLEN)) > 0) {
/* If whitespace at line start then continuation line */
if (mhdr && ossl_isspace(linebuf[0]))
state = MIME_NAME;
else
state = MIME_START;
ntmp = NULL;
/* Go through all characters */
for (p = linebuf, q = linebuf; (c = *p) && (c != '\r') && (c != '\n');
p++) {
/*
* State machine to handle MIME headers if this looks horrible
* that's because it *is*
*/
switch (state) {
case MIME_START:
if (c == ':') {
state = MIME_TYPE;
*p = 0;
ntmp = strip_ends(q);
q = p + 1;
}
break;
case MIME_TYPE:
if (c == ';') {
mime_debug("Found End Value\n");
*p = 0;
new_hdr = mime_hdr_new(ntmp, strip_ends(q));
if (new_hdr == NULL)
goto err;
if (!sk_MIME_HEADER_push(headers, new_hdr))
goto err;
mhdr = new_hdr;
new_hdr = NULL;
ntmp = NULL;
q = p + 1;
state = MIME_NAME;
} else if (c == '(') {
save_state = state;
state = MIME_COMMENT;
}
break;
case MIME_COMMENT:
if (c == ')') {
state = save_state;
}
break;
case MIME_NAME:
if (c == '=') {
state = MIME_VALUE;
*p = 0;
ntmp = strip_ends(q);
q = p + 1;
}
break;
case MIME_VALUE:
if (c == ';') {
state = MIME_NAME;
*p = 0;
mime_hdr_addparam(mhdr, ntmp, strip_ends(q));
ntmp = NULL;
q = p + 1;
} else if (c == '"') {
mime_debug("Found Quote\n");
state = MIME_QUOTE;
} else if (c == '(') {
save_state = state;
state = MIME_COMMENT;
}
break;
case MIME_QUOTE:
if (c == '"') {
mime_debug("Found Match Quote\n");
state = MIME_VALUE;
}
break;
}
}
if (state == MIME_TYPE) {
new_hdr = mime_hdr_new(ntmp, strip_ends(q));
if (new_hdr == NULL)
goto err;
if (!sk_MIME_HEADER_push(headers, new_hdr))
goto err;
mhdr = new_hdr;
new_hdr = NULL;
} else if (state == MIME_VALUE)
mime_hdr_addparam(mhdr, ntmp, strip_ends(q));
if (p == linebuf)
break; /* Blank line means end of headers */
}
return headers;
err:
mime_hdr_free(new_hdr);
sk_MIME_HEADER_pop_free(headers, mime_hdr_free);
return NULL;
}
static char *strip_ends(char *name)
{
return strip_end(strip_start(name));
}
/* Strip a parameter of whitespace from start of param */
static char *strip_start(char *name)
{
char *p, c;
/* Look for first non white space or quote */
for (p = name; (c = *p); p++) {
if (c == '"') {
/* Next char is start of string if non null */
if (p[1])
return p + 1;
/* Else null string */
return NULL;
}
if (!ossl_isspace(c))
return p;
}
return NULL;
}
/* As above but strip from end of string : maybe should handle brackets? */
static char *strip_end(char *name)
{
char *p, c;
if (!name)
return NULL;
/* Look for first non white space or quote */
for (p = name + strlen(name) - 1; p >= name; p--) {
c = *p;
if (c == '"') {
if (p - 1 == name)
return NULL;
*p = 0;
return name;
}
if (ossl_isspace(c))
*p = 0;
else
return name;
}
return NULL;
}
static MIME_HEADER *mime_hdr_new(const char *name, const char *value)
{
MIME_HEADER *mhdr = NULL;
char *tmpname = NULL, *tmpval = NULL, *p;
if (name) {
if ((tmpname = OPENSSL_strdup(name)) == NULL)
return NULL;
for (p = tmpname; *p; p++)
*p = ossl_tolower(*p);
}
if (value) {
if ((tmpval = OPENSSL_strdup(value)) == NULL)
goto err;
for (p = tmpval; *p; p++)
*p = ossl_tolower(*p);
}
mhdr = OPENSSL_malloc(sizeof(*mhdr));
if (mhdr == NULL)
goto err;
mhdr->name = tmpname;
mhdr->value = tmpval;
if ((mhdr->params = sk_MIME_PARAM_new(mime_param_cmp)) == NULL)
goto err;
return mhdr;
err:
OPENSSL_free(tmpname);
OPENSSL_free(tmpval);
OPENSSL_free(mhdr);
return NULL;
}
static int mime_hdr_addparam(MIME_HEADER *mhdr, const char *name, const char *value)
{
char *tmpname = NULL, *tmpval = NULL, *p;
MIME_PARAM *mparam = NULL;
if (name) {
tmpname = OPENSSL_strdup(name);
if (!tmpname)
goto err;
for (p = tmpname; *p; p++)
*p = ossl_tolower(*p);
}
if (value) {
tmpval = OPENSSL_strdup(value);
if (!tmpval)
goto err;
}
/* Parameter values are case sensitive so leave as is */
mparam = OPENSSL_malloc(sizeof(*mparam));
if (mparam == NULL)
goto err;
mparam->param_name = tmpname;
mparam->param_value = tmpval;
if (!sk_MIME_PARAM_push(mhdr->params, mparam))
goto err;
return 1;
err:
OPENSSL_free(tmpname);
OPENSSL_free(tmpval);
OPENSSL_free(mparam);
return 0;
}
static int mime_hdr_cmp(const MIME_HEADER *const *a,
const MIME_HEADER *const *b)
{
if (!(*a)->name || !(*b)->name)
return ! !(*a)->name - ! !(*b)->name;
return strcmp((*a)->name, (*b)->name);
}
static int mime_param_cmp(const MIME_PARAM *const *a,
const MIME_PARAM *const *b)
{
if (!(*a)->param_name || !(*b)->param_name)
return ! !(*a)->param_name - ! !(*b)->param_name;
return strcmp((*a)->param_name, (*b)->param_name);
}
/* Find a header with a given name (if possible) */
static MIME_HEADER *mime_hdr_find(STACK_OF(MIME_HEADER) *hdrs, const char *name)
{
MIME_HEADER htmp;
int idx;
htmp.name = (char *)name;
htmp.value = NULL;
htmp.params = NULL;
idx = sk_MIME_HEADER_find(hdrs, &htmp);
return sk_MIME_HEADER_value(hdrs, idx);
}
static MIME_PARAM *mime_param_find(MIME_HEADER *hdr, const char *name)
{
MIME_PARAM param;
int idx;
param.param_name = (char *)name;
param.param_value = NULL;
idx = sk_MIME_PARAM_find(hdr->params, &param);
return sk_MIME_PARAM_value(hdr->params, idx);
}
static void mime_hdr_free(MIME_HEADER *hdr)
{
if (hdr == NULL)
return;
OPENSSL_free(hdr->name);
OPENSSL_free(hdr->value);
if (hdr->params)
sk_MIME_PARAM_pop_free(hdr->params, mime_param_free);
OPENSSL_free(hdr);
}
static void mime_param_free(MIME_PARAM *param)
{
OPENSSL_free(param->param_name);
OPENSSL_free(param->param_value);
OPENSSL_free(param);
}
/*-
* Check for a multipart boundary. Returns:
* 0 : no boundary
* 1 : part boundary
* 2 : final boundary
*/
static int mime_bound_check(char *line, int linelen, const char *bound, int blen)
{
if (linelen == -1)
linelen = strlen(line);
if (blen == -1)
blen = strlen(bound);
/* Quickly eliminate if line length too short */
if (blen + 2 > linelen)
return 0;
/* Check for part boundary */
if ((strncmp(line, "--", 2) == 0)
&& strncmp(line + 2, bound, blen) == 0) {
if (strncmp(line + blen + 2, "--", 2) == 0)
return 2;
else
return 1;
}
return 0;
}
static int strip_eol(char *linebuf, int *plen, int flags)
{
int len = *plen;
char *p, c;
int is_eol = 0;
for (p = linebuf + len - 1; len > 0; len--, p--) {
c = *p;
if (c == '\n') {
is_eol = 1;
} else if (is_eol && flags & SMIME_ASCIICRLF && c == 32) {
/* Strip trailing space on a line; 32 == ASCII for ' ' */
continue;
} else if (c != '\r') {
break;
}
}
*plen = len;
return is_eol;
}

View file

@ -0,0 +1,100 @@
/*
* Copyright 2002-2018 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <stdio.h>
#include "internal/ctype.h"
#include <openssl/crypto.h>
#include "internal/cryptlib.h"
#include <openssl/conf.h>
#include <openssl/x509.h>
#include "internal/asn1_int.h"
#include "internal/objects.h"
/* Simple ASN1 OID module: add all objects in a given section */
static int do_create(const char *value, const char *name);
static int oid_module_init(CONF_IMODULE *md, const CONF *cnf)
{
int i;
const char *oid_section;
STACK_OF(CONF_VALUE) *sktmp;
CONF_VALUE *oval;
oid_section = CONF_imodule_get_value(md);
if ((sktmp = NCONF_get_section(cnf, oid_section)) == NULL) {
ASN1err(ASN1_F_OID_MODULE_INIT, ASN1_R_ERROR_LOADING_SECTION);
return 0;
}
for (i = 0; i < sk_CONF_VALUE_num(sktmp); i++) {
oval = sk_CONF_VALUE_value(sktmp, i);
if (!do_create(oval->value, oval->name)) {
ASN1err(ASN1_F_OID_MODULE_INIT, ASN1_R_ADDING_OBJECT);
return 0;
}
}
return 1;
}
static void oid_module_finish(CONF_IMODULE *md)
{
}
void ASN1_add_oid_module(void)
{
CONF_module_add("oid_section", oid_module_init, oid_module_finish);
}
/*-
* Create an OID based on a name value pair. Accept two formats.
* shortname = 1.2.3.4
* shortname = some long name, 1.2.3.4
*/
static int do_create(const char *value, const char *name)
{
int nid;
const char *ln, *ostr, *p;
char *lntmp = NULL;
p = strrchr(value, ',');
if (p == NULL) {
ln = name;
ostr = value;
} else {
ln = value;
ostr = p + 1;
if (*ostr == '\0')
return 0;
while (ossl_isspace(*ostr))
ostr++;
while (ossl_isspace(*ln))
ln++;
p--;
while (ossl_isspace(*p)) {
if (p == ln)
return 0;
p--;
}
p++;
if ((lntmp = OPENSSL_malloc((p - ln) + 1)) == NULL) {
ASN1err(ASN1_F_DO_CREATE, ERR_R_MALLOC_FAILURE);
return 0;
}
memcpy(lntmp, ln, p - ln);
lntmp[p - ln] = '\0';
ln = lntmp;
}
nid = OBJ_create(ostr, name, ln);
OPENSSL_free(lntmp);
return nid != NID_undef;
}

View file

@ -0,0 +1,113 @@
/*
* Copyright 2012-2017 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <stdio.h>
#include <openssl/crypto.h>
#include "internal/cryptlib.h"
#include <openssl/conf.h>
#include <openssl/x509v3.h>
/* Multi string module: add table entries from a given section */
static int do_tcreate(const char *value, const char *name);
static int stbl_module_init(CONF_IMODULE *md, const CONF *cnf)
{
int i;
const char *stbl_section;
STACK_OF(CONF_VALUE) *sktmp;
CONF_VALUE *mval;
stbl_section = CONF_imodule_get_value(md);
if ((sktmp = NCONF_get_section(cnf, stbl_section)) == NULL) {
ASN1err(ASN1_F_STBL_MODULE_INIT, ASN1_R_ERROR_LOADING_SECTION);
return 0;
}
for (i = 0; i < sk_CONF_VALUE_num(sktmp); i++) {
mval = sk_CONF_VALUE_value(sktmp, i);
if (!do_tcreate(mval->value, mval->name)) {
ASN1err(ASN1_F_STBL_MODULE_INIT, ASN1_R_INVALID_VALUE);
return 0;
}
}
return 1;
}
static void stbl_module_finish(CONF_IMODULE *md)
{
ASN1_STRING_TABLE_cleanup();
}
void ASN1_add_stable_module(void)
{
CONF_module_add("stbl_section", stbl_module_init, stbl_module_finish);
}
/*
* Create an table entry based on a name value pair. format is oid_name =
* n1:v1, n2:v2,... where name is "min", "max", "mask" or "flags".
*/
static int do_tcreate(const char *value, const char *name)
{
char *eptr;
int nid, i, rv = 0;
long tbl_min = -1, tbl_max = -1;
unsigned long tbl_mask = 0, tbl_flags = 0;
STACK_OF(CONF_VALUE) *lst = NULL;
CONF_VALUE *cnf = NULL;
nid = OBJ_sn2nid(name);
if (nid == NID_undef)
nid = OBJ_ln2nid(name);
if (nid == NID_undef)
goto err;
lst = X509V3_parse_list(value);
if (!lst)
goto err;
for (i = 0; i < sk_CONF_VALUE_num(lst); i++) {
cnf = sk_CONF_VALUE_value(lst, i);
if (strcmp(cnf->name, "min") == 0) {
tbl_min = strtoul(cnf->value, &eptr, 0);
if (*eptr)
goto err;
} else if (strcmp(cnf->name, "max") == 0) {
tbl_max = strtoul(cnf->value, &eptr, 0);
if (*eptr)
goto err;
} else if (strcmp(cnf->name, "mask") == 0) {
if (!ASN1_str2mask(cnf->value, &tbl_mask) || !tbl_mask)
goto err;
} else if (strcmp(cnf->name, "flags") == 0) {
if (strcmp(cnf->value, "nomask") == 0)
tbl_flags = STABLE_NO_MASK;
else if (strcmp(cnf->value, "none") == 0)
tbl_flags = STABLE_FLAGS_CLEAR;
else
goto err;
} else
goto err;
}
rv = 1;
err:
if (rv == 0) {
ASN1err(ASN1_F_DO_TCREATE, ASN1_R_INVALID_STRING_TABLE_VALUE);
if (cnf)
ERR_add_error_data(4, "field=", cnf->name,
", value=", cnf->value);
else
ERR_add_error_data(4, "name=", name, ", value=", value);
} else {
rv = ASN1_STRING_TABLE_add(nid, tbl_min, tbl_max,
tbl_mask, tbl_flags);
if (!rv)
ASN1err(ASN1_F_DO_TCREATE, ERR_R_MALLOC_FAILURE);
}
sk_CONF_VALUE_pop_free(lst, X509V3_conf_free);
return rv;
}

View file

@ -0,0 +1,62 @@
/*
* Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <stdio.h>
#include "internal/cryptlib.h"
#include <openssl/asn1.h>
/* ASN1 packing and unpacking functions */
ASN1_STRING *ASN1_item_pack(void *obj, const ASN1_ITEM *it, ASN1_STRING **oct)
{
ASN1_STRING *octmp;
if (oct == NULL || *oct == NULL) {
if ((octmp = ASN1_STRING_new()) == NULL) {
ASN1err(ASN1_F_ASN1_ITEM_PACK, ERR_R_MALLOC_FAILURE);
return NULL;
}
} else {
octmp = *oct;
}
OPENSSL_free(octmp->data);
octmp->data = NULL;
if ((octmp->length = ASN1_item_i2d(obj, &octmp->data, it)) == 0) {
ASN1err(ASN1_F_ASN1_ITEM_PACK, ASN1_R_ENCODE_ERROR);
goto err;
}
if (octmp->data == NULL) {
ASN1err(ASN1_F_ASN1_ITEM_PACK, ERR_R_MALLOC_FAILURE);
goto err;
}
if (oct != NULL && *oct == NULL)
*oct = octmp;
return octmp;
err:
if (oct == NULL || *oct == NULL)
ASN1_STRING_free(octmp);
return NULL;
}
/* Extract an ASN1 object from an ASN1_STRING */
void *ASN1_item_unpack(const ASN1_STRING *oct, const ASN1_ITEM *it)
{
const unsigned char *p;
void *ret;
p = oct->data;
if ((ret = ASN1_item_d2i(NULL, &p, oct->length, it)) == NULL)
ASN1err(ASN1_F_ASN1_ITEM_UNPACK, ASN1_R_DECODE_ERROR);
return ret;
}

View file

@ -0,0 +1,444 @@
/*
* Copyright 2006-2018 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
/*
* Experimental ASN1 BIO. When written through the data is converted to an
* ASN1 string type: default is OCTET STRING. Additional functions can be
* provided to add prefix and suffix data.
*/
#include <string.h>
#include "internal/bio.h"
#include <openssl/asn1.h>
#include "internal/cryptlib.h"
/* Must be large enough for biggest tag+length */
#define DEFAULT_ASN1_BUF_SIZE 20
typedef enum {
ASN1_STATE_START,
ASN1_STATE_PRE_COPY,
ASN1_STATE_HEADER,
ASN1_STATE_HEADER_COPY,
ASN1_STATE_DATA_COPY,
ASN1_STATE_POST_COPY,
ASN1_STATE_DONE
} asn1_bio_state_t;
typedef struct BIO_ASN1_EX_FUNCS_st {
asn1_ps_func *ex_func;
asn1_ps_func *ex_free_func;
} BIO_ASN1_EX_FUNCS;
typedef struct BIO_ASN1_BUF_CTX_t {
/* Internal state */
asn1_bio_state_t state;
/* Internal buffer */
unsigned char *buf;
/* Size of buffer */
int bufsize;
/* Current position in buffer */
int bufpos;
/* Current buffer length */
int buflen;
/* Amount of data to copy */
int copylen;
/* Class and tag to use */
int asn1_class, asn1_tag;
asn1_ps_func *prefix, *prefix_free, *suffix, *suffix_free;
/* Extra buffer for prefix and suffix data */
unsigned char *ex_buf;
int ex_len;
int ex_pos;
void *ex_arg;
} BIO_ASN1_BUF_CTX;
static int asn1_bio_write(BIO *h, const char *buf, int num);
static int asn1_bio_read(BIO *h, char *buf, int size);
static int asn1_bio_puts(BIO *h, const char *str);
static int asn1_bio_gets(BIO *h, char *str, int size);
static long asn1_bio_ctrl(BIO *h, int cmd, long arg1, void *arg2);
static int asn1_bio_new(BIO *h);
static int asn1_bio_free(BIO *data);
static long asn1_bio_callback_ctrl(BIO *h, int cmd, BIO_info_cb *fp);
static int asn1_bio_init(BIO_ASN1_BUF_CTX *ctx, int size);
static int asn1_bio_flush_ex(BIO *b, BIO_ASN1_BUF_CTX *ctx,
asn1_ps_func *cleanup, asn1_bio_state_t next);
static int asn1_bio_setup_ex(BIO *b, BIO_ASN1_BUF_CTX *ctx,
asn1_ps_func *setup,
asn1_bio_state_t ex_state,
asn1_bio_state_t other_state);
static const BIO_METHOD methods_asn1 = {
BIO_TYPE_ASN1,
"asn1",
/* TODO: Convert to new style write function */
bwrite_conv,
asn1_bio_write,
/* TODO: Convert to new style read function */
bread_conv,
asn1_bio_read,
asn1_bio_puts,
asn1_bio_gets,
asn1_bio_ctrl,
asn1_bio_new,
asn1_bio_free,
asn1_bio_callback_ctrl,
};
const BIO_METHOD *BIO_f_asn1(void)
{
return &methods_asn1;
}
static int asn1_bio_new(BIO *b)
{
BIO_ASN1_BUF_CTX *ctx = OPENSSL_zalloc(sizeof(*ctx));
if (ctx == NULL)
return 0;
if (!asn1_bio_init(ctx, DEFAULT_ASN1_BUF_SIZE)) {
OPENSSL_free(ctx);
return 0;
}
BIO_set_data(b, ctx);
BIO_set_init(b, 1);
return 1;
}
static int asn1_bio_init(BIO_ASN1_BUF_CTX *ctx, int size)
{
if ((ctx->buf = OPENSSL_malloc(size)) == NULL) {
ASN1err(ASN1_F_ASN1_BIO_INIT, ERR_R_MALLOC_FAILURE);
return 0;
}
ctx->bufsize = size;
ctx->asn1_class = V_ASN1_UNIVERSAL;
ctx->asn1_tag = V_ASN1_OCTET_STRING;
ctx->state = ASN1_STATE_START;
return 1;
}
static int asn1_bio_free(BIO *b)
{
BIO_ASN1_BUF_CTX *ctx;
if (b == NULL)
return 0;
ctx = BIO_get_data(b);
if (ctx == NULL)
return 0;
OPENSSL_free(ctx->buf);
OPENSSL_free(ctx);
BIO_set_data(b, NULL);
BIO_set_init(b, 0);
return 1;
}
static int asn1_bio_write(BIO *b, const char *in, int inl)
{
BIO_ASN1_BUF_CTX *ctx;
int wrmax, wrlen, ret;
unsigned char *p;
BIO *next;
ctx = BIO_get_data(b);
next = BIO_next(b);
if (in == NULL || inl < 0 || ctx == NULL || next == NULL)
return 0;
wrlen = 0;
ret = -1;
for (;;) {
switch (ctx->state) {
/* Setup prefix data, call it */
case ASN1_STATE_START:
if (!asn1_bio_setup_ex(b, ctx, ctx->prefix,
ASN1_STATE_PRE_COPY, ASN1_STATE_HEADER))
return 0;
break;
/* Copy any pre data first */
case ASN1_STATE_PRE_COPY:
ret = asn1_bio_flush_ex(b, ctx, ctx->prefix_free,
ASN1_STATE_HEADER);
if (ret <= 0)
goto done;
break;
case ASN1_STATE_HEADER:
ctx->buflen = ASN1_object_size(0, inl, ctx->asn1_tag) - inl;
if (!ossl_assert(ctx->buflen <= ctx->bufsize))
return 0;
p = ctx->buf;
ASN1_put_object(&p, 0, inl, ctx->asn1_tag, ctx->asn1_class);
ctx->copylen = inl;
ctx->state = ASN1_STATE_HEADER_COPY;
break;
case ASN1_STATE_HEADER_COPY:
ret = BIO_write(next, ctx->buf + ctx->bufpos, ctx->buflen);
if (ret <= 0)
goto done;
ctx->buflen -= ret;
if (ctx->buflen)
ctx->bufpos += ret;
else {
ctx->bufpos = 0;
ctx->state = ASN1_STATE_DATA_COPY;
}
break;
case ASN1_STATE_DATA_COPY:
if (inl > ctx->copylen)
wrmax = ctx->copylen;
else
wrmax = inl;
ret = BIO_write(next, in, wrmax);
if (ret <= 0)
goto done;
wrlen += ret;
ctx->copylen -= ret;
in += ret;
inl -= ret;
if (ctx->copylen == 0)
ctx->state = ASN1_STATE_HEADER;
if (inl == 0)
goto done;
break;
case ASN1_STATE_POST_COPY:
case ASN1_STATE_DONE:
BIO_clear_retry_flags(b);
return 0;
}
}
done:
BIO_clear_retry_flags(b);
BIO_copy_next_retry(b);
return (wrlen > 0) ? wrlen : ret;
}
static int asn1_bio_flush_ex(BIO *b, BIO_ASN1_BUF_CTX *ctx,
asn1_ps_func *cleanup, asn1_bio_state_t next)
{
int ret;
if (ctx->ex_len <= 0)
return 1;
for (;;) {
ret = BIO_write(BIO_next(b), ctx->ex_buf + ctx->ex_pos, ctx->ex_len);
if (ret <= 0)
break;
ctx->ex_len -= ret;
if (ctx->ex_len > 0)
ctx->ex_pos += ret;
else {
if (cleanup)
cleanup(b, &ctx->ex_buf, &ctx->ex_len, &ctx->ex_arg);
ctx->state = next;
ctx->ex_pos = 0;
break;
}
}
return ret;
}
static int asn1_bio_setup_ex(BIO *b, BIO_ASN1_BUF_CTX *ctx,
asn1_ps_func *setup,
asn1_bio_state_t ex_state,
asn1_bio_state_t other_state)
{
if (setup && !setup(b, &ctx->ex_buf, &ctx->ex_len, &ctx->ex_arg)) {
BIO_clear_retry_flags(b);
return 0;
}
if (ctx->ex_len > 0)
ctx->state = ex_state;
else
ctx->state = other_state;
return 1;
}
static int asn1_bio_read(BIO *b, char *in, int inl)
{
BIO *next = BIO_next(b);
if (next == NULL)
return 0;
return BIO_read(next, in, inl);
}
static int asn1_bio_puts(BIO *b, const char *str)
{
return asn1_bio_write(b, str, strlen(str));
}
static int asn1_bio_gets(BIO *b, char *str, int size)
{
BIO *next = BIO_next(b);
if (next == NULL)
return 0;
return BIO_gets(next, str, size);
}
static long asn1_bio_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp)
{
BIO *next = BIO_next(b);
if (next == NULL)
return 0;
return BIO_callback_ctrl(next, cmd, fp);
}
static long asn1_bio_ctrl(BIO *b, int cmd, long arg1, void *arg2)
{
BIO_ASN1_BUF_CTX *ctx;
BIO_ASN1_EX_FUNCS *ex_func;
long ret = 1;
BIO *next;
ctx = BIO_get_data(b);
if (ctx == NULL)
return 0;
next = BIO_next(b);
switch (cmd) {
case BIO_C_SET_PREFIX:
ex_func = arg2;
ctx->prefix = ex_func->ex_func;
ctx->prefix_free = ex_func->ex_free_func;
break;
case BIO_C_GET_PREFIX:
ex_func = arg2;
ex_func->ex_func = ctx->prefix;
ex_func->ex_free_func = ctx->prefix_free;
break;
case BIO_C_SET_SUFFIX:
ex_func = arg2;
ctx->suffix = ex_func->ex_func;
ctx->suffix_free = ex_func->ex_free_func;
break;
case BIO_C_GET_SUFFIX:
ex_func = arg2;
ex_func->ex_func = ctx->suffix;
ex_func->ex_free_func = ctx->suffix_free;
break;
case BIO_C_SET_EX_ARG:
ctx->ex_arg = arg2;
break;
case BIO_C_GET_EX_ARG:
*(void **)arg2 = ctx->ex_arg;
break;
case BIO_CTRL_FLUSH:
if (next == NULL)
return 0;
/* Call post function if possible */
if (ctx->state == ASN1_STATE_HEADER) {
if (!asn1_bio_setup_ex(b, ctx, ctx->suffix,
ASN1_STATE_POST_COPY, ASN1_STATE_DONE))
return 0;
}
if (ctx->state == ASN1_STATE_POST_COPY) {
ret = asn1_bio_flush_ex(b, ctx, ctx->suffix_free,
ASN1_STATE_DONE);
if (ret <= 0)
return ret;
}
if (ctx->state == ASN1_STATE_DONE)
return BIO_ctrl(next, cmd, arg1, arg2);
else {
BIO_clear_retry_flags(b);
return 0;
}
default:
if (next == NULL)
return 0;
return BIO_ctrl(next, cmd, arg1, arg2);
}
return ret;
}
static int asn1_bio_set_ex(BIO *b, int cmd,
asn1_ps_func *ex_func, asn1_ps_func *ex_free_func)
{
BIO_ASN1_EX_FUNCS extmp;
extmp.ex_func = ex_func;
extmp.ex_free_func = ex_free_func;
return BIO_ctrl(b, cmd, 0, &extmp);
}
static int asn1_bio_get_ex(BIO *b, int cmd,
asn1_ps_func **ex_func,
asn1_ps_func **ex_free_func)
{
BIO_ASN1_EX_FUNCS extmp;
int ret;
ret = BIO_ctrl(b, cmd, 0, &extmp);
if (ret > 0) {
*ex_func = extmp.ex_func;
*ex_free_func = extmp.ex_free_func;
}
return ret;
}
int BIO_asn1_set_prefix(BIO *b, asn1_ps_func *prefix,
asn1_ps_func *prefix_free)
{
return asn1_bio_set_ex(b, BIO_C_SET_PREFIX, prefix, prefix_free);
}
int BIO_asn1_get_prefix(BIO *b, asn1_ps_func **pprefix,
asn1_ps_func **pprefix_free)
{
return asn1_bio_get_ex(b, BIO_C_GET_PREFIX, pprefix, pprefix_free);
}
int BIO_asn1_set_suffix(BIO *b, asn1_ps_func *suffix,
asn1_ps_func *suffix_free)
{
return asn1_bio_set_ex(b, BIO_C_SET_SUFFIX, suffix, suffix_free);
}
int BIO_asn1_get_suffix(BIO *b, asn1_ps_func **psuffix,
asn1_ps_func **psuffix_free)
{
return asn1_bio_get_ex(b, BIO_C_GET_SUFFIX, psuffix, psuffix_free);
}

View file

@ -0,0 +1,201 @@
/*
* Copyright 2008-2018 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <openssl/asn1.h>
#include <openssl/asn1t.h>
#include <openssl/bio.h>
#include <openssl/err.h>
#include <stdio.h>
/* Experimental NDEF ASN1 BIO support routines */
/*
* The usage is quite simple, initialize an ASN1 structure, get a BIO from it
* then any data written through the BIO will end up translated to
* appropriate format on the fly. The data is streamed out and does *not*
* need to be all held in memory at once. When the BIO is flushed the output
* is finalized and any signatures etc written out. The BIO is a 'proper'
* BIO and can handle non blocking I/O correctly. The usage is simple. The
* implementation is *not*...
*/
/* BIO support data stored in the ASN1 BIO ex_arg */
typedef struct ndef_aux_st {
/* ASN1 structure this BIO refers to */
ASN1_VALUE *val;
const ASN1_ITEM *it;
/* Top of the BIO chain */
BIO *ndef_bio;
/* Output BIO */
BIO *out;
/* Boundary where content is inserted */
unsigned char **boundary;
/* DER buffer start */
unsigned char *derbuf;
} NDEF_SUPPORT;
static int ndef_prefix(BIO *b, unsigned char **pbuf, int *plen, void *parg);
static int ndef_prefix_free(BIO *b, unsigned char **pbuf, int *plen,
void *parg);
static int ndef_suffix(BIO *b, unsigned char **pbuf, int *plen, void *parg);
static int ndef_suffix_free(BIO *b, unsigned char **pbuf, int *plen,
void *parg);
BIO *BIO_new_NDEF(BIO *out, ASN1_VALUE *val, const ASN1_ITEM *it)
{
NDEF_SUPPORT *ndef_aux = NULL;
BIO *asn_bio = NULL;
const ASN1_AUX *aux = it->funcs;
ASN1_STREAM_ARG sarg;
if (!aux || !aux->asn1_cb) {
ASN1err(ASN1_F_BIO_NEW_NDEF, ASN1_R_STREAMING_NOT_SUPPORTED);
return NULL;
}
ndef_aux = OPENSSL_zalloc(sizeof(*ndef_aux));
asn_bio = BIO_new(BIO_f_asn1());
if (ndef_aux == NULL || asn_bio == NULL)
goto err;
/* ASN1 bio needs to be next to output BIO */
out = BIO_push(asn_bio, out);
if (out == NULL)
goto err;
BIO_asn1_set_prefix(asn_bio, ndef_prefix, ndef_prefix_free);
BIO_asn1_set_suffix(asn_bio, ndef_suffix, ndef_suffix_free);
/*
* Now let callback prepends any digest, cipher etc BIOs ASN1 structure
* needs.
*/
sarg.out = out;
sarg.ndef_bio = NULL;
sarg.boundary = NULL;
if (aux->asn1_cb(ASN1_OP_STREAM_PRE, &val, it, &sarg) <= 0)
goto err;
ndef_aux->val = val;
ndef_aux->it = it;
ndef_aux->ndef_bio = sarg.ndef_bio;
ndef_aux->boundary = sarg.boundary;
ndef_aux->out = out;
BIO_ctrl(asn_bio, BIO_C_SET_EX_ARG, 0, ndef_aux);
return sarg.ndef_bio;
err:
BIO_free(asn_bio);
OPENSSL_free(ndef_aux);
return NULL;
}
static int ndef_prefix(BIO *b, unsigned char **pbuf, int *plen, void *parg)
{
NDEF_SUPPORT *ndef_aux;
unsigned char *p;
int derlen;
if (!parg)
return 0;
ndef_aux = *(NDEF_SUPPORT **)parg;
derlen = ASN1_item_ndef_i2d(ndef_aux->val, NULL, ndef_aux->it);
if ((p = OPENSSL_malloc(derlen)) == NULL) {
ASN1err(ASN1_F_NDEF_PREFIX, ERR_R_MALLOC_FAILURE);
return 0;
}
ndef_aux->derbuf = p;
*pbuf = p;
derlen = ASN1_item_ndef_i2d(ndef_aux->val, &p, ndef_aux->it);
if (!*ndef_aux->boundary)
return 0;
*plen = *ndef_aux->boundary - *pbuf;
return 1;
}
static int ndef_prefix_free(BIO *b, unsigned char **pbuf, int *plen,
void *parg)
{
NDEF_SUPPORT *ndef_aux;
if (!parg)
return 0;
ndef_aux = *(NDEF_SUPPORT **)parg;
OPENSSL_free(ndef_aux->derbuf);
ndef_aux->derbuf = NULL;
*pbuf = NULL;
*plen = 0;
return 1;
}
static int ndef_suffix_free(BIO *b, unsigned char **pbuf, int *plen,
void *parg)
{
NDEF_SUPPORT **pndef_aux = (NDEF_SUPPORT **)parg;
if (!ndef_prefix_free(b, pbuf, plen, parg))
return 0;
OPENSSL_free(*pndef_aux);
*pndef_aux = NULL;
return 1;
}
static int ndef_suffix(BIO *b, unsigned char **pbuf, int *plen, void *parg)
{
NDEF_SUPPORT *ndef_aux;
unsigned char *p;
int derlen;
const ASN1_AUX *aux;
ASN1_STREAM_ARG sarg;
if (!parg)
return 0;
ndef_aux = *(NDEF_SUPPORT **)parg;
aux = ndef_aux->it->funcs;
/* Finalize structures */
sarg.ndef_bio = ndef_aux->ndef_bio;
sarg.out = ndef_aux->out;
sarg.boundary = ndef_aux->boundary;
if (aux->asn1_cb(ASN1_OP_STREAM_POST,
&ndef_aux->val, ndef_aux->it, &sarg) <= 0)
return 0;
derlen = ASN1_item_ndef_i2d(ndef_aux->val, NULL, ndef_aux->it);
if ((p = OPENSSL_malloc(derlen)) == NULL) {
ASN1err(ASN1_F_NDEF_SUFFIX, ERR_R_MALLOC_FAILURE);
return 0;
}
ndef_aux->derbuf = p;
*pbuf = p;
derlen = ASN1_item_ndef_i2d(ndef_aux->val, &p, ndef_aux->it);
if (!*ndef_aux->boundary)
return 0;
*pbuf = *ndef_aux->boundary;
*plen = derlen - (*ndef_aux->boundary - ndef_aux->derbuf);
return 1;
}

View file

@ -0,0 +1,16 @@
LIBS=../../libcrypto
SOURCE[../../libcrypto]=\
a_object.c a_bitstr.c a_utctm.c a_gentm.c a_time.c a_int.c a_octet.c \
a_print.c a_type.c a_dup.c a_d2i_fp.c a_i2d_fp.c \
a_utf8.c a_sign.c a_digest.c a_verify.c a_mbstr.c a_strex.c \
x_algor.c x_val.c x_sig.c x_bignum.c \
x_long.c x_int64.c x_info.c x_spki.c nsseq.c \
d2i_pu.c d2i_pr.c i2d_pu.c i2d_pr.c\
t_pkey.c t_spki.c t_bitst.c \
tasn_new.c tasn_fre.c tasn_enc.c tasn_dec.c tasn_utl.c tasn_typ.c \
tasn_prn.c tasn_scn.c ameth_lib.c \
f_int.c f_string.c n_pkey.c \
x_pkey.c bio_asn1.c bio_ndef.c asn_mime.c \
asn1_gen.c asn1_par.c asn1_lib.c asn1_err.c a_strnid.c \
evp_asn1.c asn_pack.c p5_pbe.c p5_pbev2.c p5_scrypt.c p8_pkey.c \
asn_moid.c asn_mstbl.c asn1_item_list.c

View file

@ -0,0 +1,34 @@
/*
* WARNING: do not edit!
* Generated by crypto/asn1/charmap.pl
*
* Copyright 2000-2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#define CHARTYPE_HOST_ANY 4096
#define CHARTYPE_HOST_DOT 8192
#define CHARTYPE_HOST_HYPHEN 16384
#define CHARTYPE_HOST_WILD 32768
/*
* Mask of various character properties
*/
static const unsigned short char_type[] = {
1026, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 120, 0, 1, 40,
0, 0, 0, 16, 1040, 1040, 33792, 25, 25, 16400, 8208, 16,
4112, 4112, 4112, 4112, 4112, 4112, 4112, 4112, 4112, 4112, 16, 9,
9, 16, 9, 16, 0, 4112, 4112, 4112, 4112, 4112, 4112, 4112,
4112, 4112, 4112, 4112, 4112, 4112, 4112, 4112, 4112, 4112, 4112, 4112,
4112, 4112, 4112, 4112, 4112, 4112, 4112, 0, 1025, 0, 0, 0,
0, 4112, 4112, 4112, 4112, 4112, 4112, 4112, 4112, 4112, 4112, 4112,
4112, 4112, 4112, 4112, 4112, 4112, 4112, 4112, 4112, 4112, 4112, 4112,
4112, 4112, 4112, 0, 0, 0, 0, 2
};

View file

@ -0,0 +1,119 @@
#! /usr/bin/env perl
# Copyright 2000-2019 The OpenSSL Project Authors. All Rights Reserved.
#
# Licensed under the OpenSSL license (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
use strict;
my ($i, @arr);
# Set up an array with the type of ASCII characters
# Each set bit represents a character property.
# RFC2253 character properties
my $RFC2253_ESC = 1; # Character escaped with \
my $ESC_CTRL = 2; # Escaped control character
# These are used with RFC1779 quoting using "
my $NOESC_QUOTE = 8; # Not escaped if quoted
my $PSTRING_CHAR = 0x10; # Valid PrintableString character
my $RFC2253_FIRST_ESC = 0x20; # Escaped with \ if first character
my $RFC2253_LAST_ESC = 0x40; # Escaped with \ if last character
my $RFC2254_ESC = 0x400; # Character escaped \XX
my $HOST_ANY = 0x1000; # Valid hostname character anywhere in label
my $HOST_DOT = 0x2000; # Dot: hostname label separator
my $HOST_HYPHEN = 0x4000; # Hyphen: not valid at start or end.
my $HOST_WILD = 0x8000; # Wildcard character
for($i = 0; $i < 128; $i++) {
# Set the RFC2253 escape characters (control)
$arr[$i] = 0;
if(($i < 32) || ($i > 126)) {
$arr[$i] |= $ESC_CTRL;
}
# Some PrintableString characters
if( ( ( $i >= ord("a")) && ( $i <= ord("z")) )
|| ( ( $i >= ord("A")) && ( $i <= ord("Z")) )
|| ( ( $i >= ord("0")) && ( $i <= ord("9")) ) ) {
$arr[$i] |= $PSTRING_CHAR | $HOST_ANY;
}
}
# Now setup the rest
# Remaining RFC2253 escaped characters
$arr[ord(" ")] |= $NOESC_QUOTE | $RFC2253_FIRST_ESC | $RFC2253_LAST_ESC;
$arr[ord("#")] |= $NOESC_QUOTE | $RFC2253_FIRST_ESC;
$arr[ord(",")] |= $NOESC_QUOTE | $RFC2253_ESC;
$arr[ord("+")] |= $NOESC_QUOTE | $RFC2253_ESC;
$arr[ord("\"")] |= $RFC2253_ESC;
$arr[ord("\\")] |= $RFC2253_ESC;
$arr[ord("<")] |= $NOESC_QUOTE | $RFC2253_ESC;
$arr[ord(">")] |= $NOESC_QUOTE | $RFC2253_ESC;
$arr[ord(";")] |= $NOESC_QUOTE | $RFC2253_ESC;
# Remaining RFC2254 characters
$arr[0] |= $RFC2254_ESC;
$arr[ord("(")] |= $RFC2254_ESC;
$arr[ord(")")] |= $RFC2254_ESC;
$arr[ord("*")] |= $RFC2254_ESC | $HOST_WILD;
$arr[ord("\\")] |= $RFC2254_ESC;
# Remaining PrintableString characters
$arr[ord(" ")] |= $PSTRING_CHAR;
$arr[ord("'")] |= $PSTRING_CHAR;
$arr[ord("(")] |= $PSTRING_CHAR;
$arr[ord(")")] |= $PSTRING_CHAR;
$arr[ord("+")] |= $PSTRING_CHAR;
$arr[ord(",")] |= $PSTRING_CHAR;
$arr[ord("-")] |= $PSTRING_CHAR | $HOST_HYPHEN;
$arr[ord(".")] |= $PSTRING_CHAR | $HOST_DOT;
$arr[ord("/")] |= $PSTRING_CHAR;
$arr[ord(":")] |= $PSTRING_CHAR;
$arr[ord("=")] |= $PSTRING_CHAR;
$arr[ord("?")] |= $PSTRING_CHAR;
# Now generate the C code
# Output year depends on the year of the script.
my $YEAR = [localtime([stat($0)]->[9])]->[5] + 1900;
print <<EOF;
/*
* WARNING: do not edit!
* Generated by crypto/asn1/charmap.pl
*
* Copyright 2000-$YEAR The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#define CHARTYPE_HOST_ANY $HOST_ANY
#define CHARTYPE_HOST_DOT $HOST_DOT
#define CHARTYPE_HOST_HYPHEN $HOST_HYPHEN
#define CHARTYPE_HOST_WILD $HOST_WILD
/*
* Mask of various character properties
*/
static const unsigned short char_type[] = {
EOF
print " ";
for($i = 0; $i < 128; $i++) {
print("\n ") if($i && (($i % 12) == 0));
printf(" %4d", $arr[$i]);
print(",") if ($i != 127);
}
print("\n};\n");

View file

@ -0,0 +1,125 @@
/*
* Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <stdio.h>
#include "internal/cryptlib.h"
#include <openssl/bn.h>
#include <openssl/evp.h>
#include <openssl/objects.h>
#include <openssl/engine.h>
#include <openssl/x509.h>
#include <openssl/asn1.h>
#include "internal/asn1_int.h"
#include "internal/evp_int.h"
EVP_PKEY *d2i_PrivateKey(int type, EVP_PKEY **a, const unsigned char **pp,
long length)
{
EVP_PKEY *ret;
const unsigned char *p = *pp;
if ((a == NULL) || (*a == NULL)) {
if ((ret = EVP_PKEY_new()) == NULL) {
ASN1err(ASN1_F_D2I_PRIVATEKEY, ERR_R_EVP_LIB);
return NULL;
}
} else {
ret = *a;
#ifndef OPENSSL_NO_ENGINE
ENGINE_finish(ret->engine);
ret->engine = NULL;
#endif
}
if (!EVP_PKEY_set_type(ret, type)) {
ASN1err(ASN1_F_D2I_PRIVATEKEY, ASN1_R_UNKNOWN_PUBLIC_KEY_TYPE);
goto err;
}
if (!ret->ameth->old_priv_decode ||
!ret->ameth->old_priv_decode(ret, &p, length)) {
if (ret->ameth->priv_decode) {
EVP_PKEY *tmp;
PKCS8_PRIV_KEY_INFO *p8 = NULL;
p8 = d2i_PKCS8_PRIV_KEY_INFO(NULL, &p, length);
if (!p8)
goto err;
tmp = EVP_PKCS82PKEY(p8);
PKCS8_PRIV_KEY_INFO_free(p8);
if (tmp == NULL)
goto err;
EVP_PKEY_free(ret);
ret = tmp;
} else {
ASN1err(ASN1_F_D2I_PRIVATEKEY, ERR_R_ASN1_LIB);
goto err;
}
}
*pp = p;
if (a != NULL)
(*a) = ret;
return ret;
err:
if (a == NULL || *a != ret)
EVP_PKEY_free(ret);
return NULL;
}
/*
* This works like d2i_PrivateKey() except it automatically works out the
* type
*/
EVP_PKEY *d2i_AutoPrivateKey(EVP_PKEY **a, const unsigned char **pp,
long length)
{
STACK_OF(ASN1_TYPE) *inkey;
const unsigned char *p;
int keytype;
p = *pp;
/*
* Dirty trick: read in the ASN1 data into a STACK_OF(ASN1_TYPE): by
* analyzing it we can determine the passed structure: this assumes the
* input is surrounded by an ASN1 SEQUENCE.
*/
inkey = d2i_ASN1_SEQUENCE_ANY(NULL, &p, length);
p = *pp;
/*
* Since we only need to discern "traditional format" RSA and DSA keys we
* can just count the elements.
*/
if (sk_ASN1_TYPE_num(inkey) == 6)
keytype = EVP_PKEY_DSA;
else if (sk_ASN1_TYPE_num(inkey) == 4)
keytype = EVP_PKEY_EC;
else if (sk_ASN1_TYPE_num(inkey) == 3) { /* This seems to be PKCS8, not
* traditional format */
PKCS8_PRIV_KEY_INFO *p8 = d2i_PKCS8_PRIV_KEY_INFO(NULL, &p, length);
EVP_PKEY *ret;
sk_ASN1_TYPE_pop_free(inkey, ASN1_TYPE_free);
if (!p8) {
ASN1err(ASN1_F_D2I_AUTOPRIVATEKEY,
ASN1_R_UNSUPPORTED_PUBLIC_KEY_TYPE);
return NULL;
}
ret = EVP_PKCS82PKEY(p8);
PKCS8_PRIV_KEY_INFO_free(p8);
if (ret == NULL)
return NULL;
*pp = p;
if (a) {
*a = ret;
}
return ret;
} else
keytype = EVP_PKEY_RSA;
sk_ASN1_TYPE_pop_free(inkey, ASN1_TYPE_free);
return d2i_PrivateKey(keytype, a, pp, length);
}

View file

@ -0,0 +1,77 @@
/*
* Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <stdio.h>
#include "internal/cryptlib.h"
#include <openssl/bn.h>
#include <openssl/evp.h>
#include <openssl/objects.h>
#include <openssl/asn1.h>
#include <openssl/rsa.h>
#include <openssl/dsa.h>
#include <openssl/ec.h>
#include "internal/evp_int.h"
EVP_PKEY *d2i_PublicKey(int type, EVP_PKEY **a, const unsigned char **pp,
long length)
{
EVP_PKEY *ret;
if ((a == NULL) || (*a == NULL)) {
if ((ret = EVP_PKEY_new()) == NULL) {
ASN1err(ASN1_F_D2I_PUBLICKEY, ERR_R_EVP_LIB);
return NULL;
}
} else
ret = *a;
if (type != EVP_PKEY_id(ret) && !EVP_PKEY_set_type(ret, type)) {
ASN1err(ASN1_F_D2I_PUBLICKEY, ERR_R_EVP_LIB);
goto err;
}
switch (EVP_PKEY_id(ret)) {
#ifndef OPENSSL_NO_RSA
case EVP_PKEY_RSA:
if ((ret->pkey.rsa = d2i_RSAPublicKey(NULL, pp, length)) == NULL) {
ASN1err(ASN1_F_D2I_PUBLICKEY, ERR_R_ASN1_LIB);
goto err;
}
break;
#endif
#ifndef OPENSSL_NO_DSA
case EVP_PKEY_DSA:
/* TMP UGLY CAST */
if (!d2i_DSAPublicKey(&ret->pkey.dsa, pp, length)) {
ASN1err(ASN1_F_D2I_PUBLICKEY, ERR_R_ASN1_LIB);
goto err;
}
break;
#endif
#ifndef OPENSSL_NO_EC
case EVP_PKEY_EC:
if (!o2i_ECPublicKey(&ret->pkey.ec, pp, length)) {
ASN1err(ASN1_F_D2I_PUBLICKEY, ERR_R_ASN1_LIB);
goto err;
}
break;
#endif
default:
ASN1err(ASN1_F_D2I_PUBLICKEY, ASN1_R_UNKNOWN_PUBLIC_KEY_TYPE);
goto err;
}
if (a != NULL)
(*a) = ret;
return ret;
err:
if (a == NULL || *a != ret)
EVP_PKEY_free(ret);
return NULL;
}

View file

@ -0,0 +1,115 @@
/*
* Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <stdio.h>
#include "internal/cryptlib.h"
#include <openssl/asn1.h>
#include <openssl/asn1t.h>
int ASN1_TYPE_set_octetstring(ASN1_TYPE *a, unsigned char *data, int len)
{
ASN1_STRING *os;
if ((os = ASN1_OCTET_STRING_new()) == NULL)
return 0;
if (!ASN1_OCTET_STRING_set(os, data, len)) {
ASN1_OCTET_STRING_free(os);
return 0;
}
ASN1_TYPE_set(a, V_ASN1_OCTET_STRING, os);
return 1;
}
/* int max_len: for returned value */
int ASN1_TYPE_get_octetstring(const ASN1_TYPE *a, unsigned char *data, int max_len)
{
int ret, num;
const unsigned char *p;
if ((a->type != V_ASN1_OCTET_STRING) || (a->value.octet_string == NULL)) {
ASN1err(ASN1_F_ASN1_TYPE_GET_OCTETSTRING, ASN1_R_DATA_IS_WRONG);
return -1;
}
p = ASN1_STRING_get0_data(a->value.octet_string);
ret = ASN1_STRING_length(a->value.octet_string);
if (ret < max_len)
num = ret;
else
num = max_len;
memcpy(data, p, num);
return ret;
}
typedef struct {
int32_t num;
ASN1_OCTET_STRING *oct;
} asn1_int_oct;
ASN1_SEQUENCE(asn1_int_oct) = {
ASN1_EMBED(asn1_int_oct, num, INT32),
ASN1_SIMPLE(asn1_int_oct, oct, ASN1_OCTET_STRING)
} static_ASN1_SEQUENCE_END(asn1_int_oct)
DECLARE_ASN1_ITEM(asn1_int_oct)
int ASN1_TYPE_set_int_octetstring(ASN1_TYPE *a, long num, unsigned char *data,
int len)
{
asn1_int_oct atmp;
ASN1_OCTET_STRING oct;
atmp.num = num;
atmp.oct = &oct;
oct.data = data;
oct.type = V_ASN1_OCTET_STRING;
oct.length = len;
oct.flags = 0;
if (ASN1_TYPE_pack_sequence(ASN1_ITEM_rptr(asn1_int_oct), &atmp, &a))
return 1;
return 0;
}
/*
* we return the actual length...
*/
/* int max_len: for returned value */
int ASN1_TYPE_get_int_octetstring(const ASN1_TYPE *a, long *num,
unsigned char *data, int max_len)
{
asn1_int_oct *atmp = NULL;
int ret = -1, n;
if ((a->type != V_ASN1_SEQUENCE) || (a->value.sequence == NULL)) {
goto err;
}
atmp = ASN1_TYPE_unpack_sequence(ASN1_ITEM_rptr(asn1_int_oct), a);
if (atmp == NULL)
goto err;
if (num != NULL)
*num = atmp->num;
ret = ASN1_STRING_length(atmp->oct);
if (max_len > ret)
n = ret;
else
n = max_len;
if (data != NULL)
memcpy(data, ASN1_STRING_get0_data(atmp->oct), n);
if (ret == -1) {
err:
ASN1err(ASN1_F_ASN1_TYPE_GET_INT_OCTETSTRING, ASN1_R_DATA_IS_WRONG);
}
M_ASN1_free_of(atmp, asn1_int_oct);
return ret;
}

View file

@ -0,0 +1,156 @@
/*
* Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <stdio.h>
#include "internal/ctype.h"
#include "internal/cryptlib.h"
#include <openssl/buffer.h>
#include <openssl/asn1.h>
int i2a_ASN1_INTEGER(BIO *bp, const ASN1_INTEGER *a)
{
int i, n = 0;
static const char *h = "0123456789ABCDEF";
char buf[2];
if (a == NULL)
return 0;
if (a->type & V_ASN1_NEG) {
if (BIO_write(bp, "-", 1) != 1)
goto err;
n = 1;
}
if (a->length == 0) {
if (BIO_write(bp, "00", 2) != 2)
goto err;
n += 2;
} else {
for (i = 0; i < a->length; i++) {
if ((i != 0) && (i % 35 == 0)) {
if (BIO_write(bp, "\\\n", 2) != 2)
goto err;
n += 2;
}
buf[0] = h[((unsigned char)a->data[i] >> 4) & 0x0f];
buf[1] = h[((unsigned char)a->data[i]) & 0x0f];
if (BIO_write(bp, buf, 2) != 2)
goto err;
n += 2;
}
}
return n;
err:
return -1;
}
int a2i_ASN1_INTEGER(BIO *bp, ASN1_INTEGER *bs, char *buf, int size)
{
int i, j, k, m, n, again, bufsize;
unsigned char *s = NULL, *sp;
unsigned char *bufp;
int num = 0, slen = 0, first = 1;
bs->type = V_ASN1_INTEGER;
bufsize = BIO_gets(bp, buf, size);
for (;;) {
if (bufsize < 1)
goto err;
i = bufsize;
if (buf[i - 1] == '\n')
buf[--i] = '\0';
if (i == 0)
goto err;
if (buf[i - 1] == '\r')
buf[--i] = '\0';
if (i == 0)
goto err;
again = (buf[i - 1] == '\\');
for (j = 0; j < i; j++) {
if (!ossl_isxdigit(buf[j]))
{
i = j;
break;
}
}
buf[i] = '\0';
/*
* We have now cleared all the crap off the end of the line
*/
if (i < 2)
goto err;
bufp = (unsigned char *)buf;
if (first) {
first = 0;
if ((bufp[0] == '0') && (bufp[1] == '0')) {
bufp += 2;
i -= 2;
}
}
k = 0;
i -= again;
if (i % 2 != 0) {
ASN1err(ASN1_F_A2I_ASN1_INTEGER, ASN1_R_ODD_NUMBER_OF_CHARS);
OPENSSL_free(s);
return 0;
}
i /= 2;
if (num + i > slen) {
sp = OPENSSL_clear_realloc(s, slen, num + i * 2);
if (sp == NULL) {
ASN1err(ASN1_F_A2I_ASN1_INTEGER, ERR_R_MALLOC_FAILURE);
OPENSSL_free(s);
return 0;
}
s = sp;
slen = num + i * 2;
}
for (j = 0; j < i; j++, k += 2) {
for (n = 0; n < 2; n++) {
m = OPENSSL_hexchar2int(bufp[k + n]);
if (m < 0) {
ASN1err(ASN1_F_A2I_ASN1_INTEGER,
ASN1_R_NON_HEX_CHARACTERS);
goto err;
}
s[num + j] <<= 4;
s[num + j] |= m;
}
}
num += i;
if (again)
bufsize = BIO_gets(bp, buf, size);
else
break;
}
bs->length = num;
bs->data = s;
return 1;
err:
ASN1err(ASN1_F_A2I_ASN1_INTEGER, ASN1_R_SHORT_LINE);
OPENSSL_free(s);
return 0;
}
int i2a_ASN1_ENUMERATED(BIO *bp, const ASN1_ENUMERATED *a)
{
return i2a_ASN1_INTEGER(bp, a);
}
int a2i_ASN1_ENUMERATED(BIO *bp, ASN1_ENUMERATED *bs, char *buf, int size)
{
int rv = a2i_ASN1_INTEGER(bp, bs, buf, size);
if (rv == 1)
bs->type = V_ASN1_INTEGER | (bs->type & V_ASN1_NEG);
return rv;
}

View file

@ -0,0 +1,136 @@
/*
* Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <stdio.h>
#include "internal/ctype.h"
#include "internal/cryptlib.h"
#include <openssl/buffer.h>
#include <openssl/asn1.h>
int i2a_ASN1_STRING(BIO *bp, const ASN1_STRING *a, int type)
{
int i, n = 0;
static const char *h = "0123456789ABCDEF";
char buf[2];
if (a == NULL)
return 0;
if (a->length == 0) {
if (BIO_write(bp, "0", 1) != 1)
goto err;
n = 1;
} else {
for (i = 0; i < a->length; i++) {
if ((i != 0) && (i % 35 == 0)) {
if (BIO_write(bp, "\\\n", 2) != 2)
goto err;
n += 2;
}
buf[0] = h[((unsigned char)a->data[i] >> 4) & 0x0f];
buf[1] = h[((unsigned char)a->data[i]) & 0x0f];
if (BIO_write(bp, buf, 2) != 2)
goto err;
n += 2;
}
}
return n;
err:
return -1;
}
int a2i_ASN1_STRING(BIO *bp, ASN1_STRING *bs, char *buf, int size)
{
int i, j, k, m, n, again, bufsize;
unsigned char *s = NULL, *sp;
unsigned char *bufp;
int num = 0, slen = 0, first = 1;
bufsize = BIO_gets(bp, buf, size);
for (;;) {
if (bufsize < 1) {
if (first)
break;
else
goto err;
}
first = 0;
i = bufsize;
if (buf[i - 1] == '\n')
buf[--i] = '\0';
if (i == 0)
goto err;
if (buf[i - 1] == '\r')
buf[--i] = '\0';
if (i == 0)
goto err;
again = (buf[i - 1] == '\\');
for (j = i - 1; j > 0; j--) {
if (!ossl_isxdigit(buf[j])) {
i = j;
break;
}
}
buf[i] = '\0';
/*
* We have now cleared all the crap off the end of the line
*/
if (i < 2)
goto err;
bufp = (unsigned char *)buf;
k = 0;
i -= again;
if (i % 2 != 0) {
ASN1err(ASN1_F_A2I_ASN1_STRING, ASN1_R_ODD_NUMBER_OF_CHARS);
OPENSSL_free(s);
return 0;
}
i /= 2;
if (num + i > slen) {
sp = OPENSSL_realloc(s, (unsigned int)num + i * 2);
if (sp == NULL) {
ASN1err(ASN1_F_A2I_ASN1_STRING, ERR_R_MALLOC_FAILURE);
OPENSSL_free(s);
return 0;
}
s = sp;
slen = num + i * 2;
}
for (j = 0; j < i; j++, k += 2) {
for (n = 0; n < 2; n++) {
m = OPENSSL_hexchar2int(bufp[k + n]);
if (m < 0) {
ASN1err(ASN1_F_A2I_ASN1_STRING,
ASN1_R_NON_HEX_CHARACTERS);
OPENSSL_free(s);
return 0;
}
s[num + j] <<= 4;
s[num + j] |= m;
}
}
num += i;
if (again)
bufsize = BIO_gets(bp, buf, size);
else
break;
}
bs->length = num;
bs->data = s;
return 1;
err:
ASN1err(ASN1_F_A2I_ASN1_STRING, ASN1_R_SHORT_LINE);
OPENSSL_free(s);
return 0;
}

View file

@ -0,0 +1,33 @@
/*
* Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <stdio.h>
#include "internal/cryptlib.h"
#include <openssl/evp.h>
#include <openssl/x509.h>
#include "internal/asn1_int.h"
#include "internal/evp_int.h"
int i2d_PrivateKey(EVP_PKEY *a, unsigned char **pp)
{
if (a->ameth && a->ameth->old_priv_encode) {
return a->ameth->old_priv_encode(a, pp);
}
if (a->ameth && a->ameth->priv_encode) {
PKCS8_PRIV_KEY_INFO *p8 = EVP_PKEY2PKCS8(a);
int ret = 0;
if (p8 != NULL) {
ret = i2d_PKCS8_PRIV_KEY_INFO(p8, pp);
PKCS8_PRIV_KEY_INFO_free(p8);
}
return ret;
}
ASN1err(ASN1_F_I2D_PRIVATEKEY, ASN1_R_UNSUPPORTED_PUBLIC_KEY_TYPE);
return -1;
}

View file

@ -0,0 +1,38 @@
/*
* Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <stdio.h>
#include "internal/cryptlib.h"
#include <openssl/bn.h>
#include <openssl/evp.h>
#include <openssl/objects.h>
#include <openssl/rsa.h>
#include <openssl/dsa.h>
#include <openssl/ec.h>
int i2d_PublicKey(EVP_PKEY *a, unsigned char **pp)
{
switch (EVP_PKEY_id(a)) {
#ifndef OPENSSL_NO_RSA
case EVP_PKEY_RSA:
return i2d_RSAPublicKey(EVP_PKEY_get0_RSA(a), pp);
#endif
#ifndef OPENSSL_NO_DSA
case EVP_PKEY_DSA:
return i2d_DSAPublicKey(EVP_PKEY_get0_DSA(a), pp);
#endif
#ifndef OPENSSL_NO_EC
case EVP_PKEY_EC:
return i2o_ECPublicKey(EVP_PKEY_get0_EC_KEY(a), pp);
#endif
default:
ASN1err(ASN1_F_I2D_PUBLICKEY, ASN1_R_UNSUPPORTED_PUBLIC_KEY_TYPE);
return -1;
}
}

View file

@ -0,0 +1,62 @@
/*
* Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include "openssl/opensslconf.h"
#ifdef OPENSSL_NO_RSA
NON_EMPTY_TRANSLATION_UNIT
#else
# include "internal/cryptlib.h"
# include <stdio.h>
# include <openssl/rsa.h>
# include <openssl/objects.h>
# include <openssl/asn1t.h>
# include <openssl/evp.h>
# include <openssl/x509.h>
# ifndef OPENSSL_NO_RC4
typedef struct netscape_pkey_st {
int32_t version;
X509_ALGOR *algor;
ASN1_OCTET_STRING *private_key;
} NETSCAPE_PKEY;
typedef struct netscape_encrypted_pkey_st {
ASN1_OCTET_STRING *os;
/*
* This is the same structure as DigestInfo so use it: although this
* isn't really anything to do with digests.
*/
X509_SIG *enckey;
} NETSCAPE_ENCRYPTED_PKEY;
ASN1_BROKEN_SEQUENCE(NETSCAPE_ENCRYPTED_PKEY) = {
ASN1_SIMPLE(NETSCAPE_ENCRYPTED_PKEY, os, ASN1_OCTET_STRING),
ASN1_SIMPLE(NETSCAPE_ENCRYPTED_PKEY, enckey, X509_SIG)
} static_ASN1_BROKEN_SEQUENCE_END(NETSCAPE_ENCRYPTED_PKEY)
DECLARE_ASN1_FUNCTIONS_const(NETSCAPE_ENCRYPTED_PKEY)
DECLARE_ASN1_ENCODE_FUNCTIONS_const(NETSCAPE_ENCRYPTED_PKEY,NETSCAPE_ENCRYPTED_PKEY)
IMPLEMENT_ASN1_FUNCTIONS_const(NETSCAPE_ENCRYPTED_PKEY)
ASN1_SEQUENCE(NETSCAPE_PKEY) = {
ASN1_EMBED(NETSCAPE_PKEY, version, INT32),
ASN1_SIMPLE(NETSCAPE_PKEY, algor, X509_ALGOR),
ASN1_SIMPLE(NETSCAPE_PKEY, private_key, ASN1_OCTET_STRING)
} static_ASN1_SEQUENCE_END(NETSCAPE_PKEY)
DECLARE_ASN1_FUNCTIONS_const(NETSCAPE_PKEY)
DECLARE_ASN1_ENCODE_FUNCTIONS_const(NETSCAPE_PKEY,NETSCAPE_PKEY)
IMPLEMENT_ASN1_FUNCTIONS_const(NETSCAPE_PKEY)
# endif /* OPENSSL_NO_RC4 */
#endif

View file

@ -0,0 +1,34 @@
/*
* Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <stdio.h>
#include <stdlib.h>
#include <openssl/asn1t.h>
#include <openssl/x509.h>
#include <openssl/objects.h>
static int nsseq_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
void *exarg)
{
if (operation == ASN1_OP_NEW_POST) {
NETSCAPE_CERT_SEQUENCE *nsseq;
nsseq = (NETSCAPE_CERT_SEQUENCE *)*pval;
nsseq->type = OBJ_nid2obj(NID_netscape_cert_sequence);
}
return 1;
}
/* Netscape certificate sequence structure */
ASN1_SEQUENCE_cb(NETSCAPE_CERT_SEQUENCE, nsseq_cb) = {
ASN1_SIMPLE(NETSCAPE_CERT_SEQUENCE, type, ASN1_OBJECT),
ASN1_EXP_SEQUENCE_OF_OPT(NETSCAPE_CERT_SEQUENCE, certs, X509, 0)
} ASN1_SEQUENCE_END_cb(NETSCAPE_CERT_SEQUENCE, NETSCAPE_CERT_SEQUENCE)
IMPLEMENT_ASN1_FUNCTIONS(NETSCAPE_CERT_SEQUENCE)

View file

@ -0,0 +1,96 @@
/*
* Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <stdio.h>
#include "internal/cryptlib.h"
#include <openssl/asn1t.h>
#include <openssl/x509.h>
#include <openssl/rand.h>
/* PKCS#5 password based encryption structure */
ASN1_SEQUENCE(PBEPARAM) = {
ASN1_SIMPLE(PBEPARAM, salt, ASN1_OCTET_STRING),
ASN1_SIMPLE(PBEPARAM, iter, ASN1_INTEGER)
} ASN1_SEQUENCE_END(PBEPARAM)
IMPLEMENT_ASN1_FUNCTIONS(PBEPARAM)
/* Set an algorithm identifier for a PKCS#5 PBE algorithm */
int PKCS5_pbe_set0_algor(X509_ALGOR *algor, int alg, int iter,
const unsigned char *salt, int saltlen)
{
PBEPARAM *pbe = NULL;
ASN1_STRING *pbe_str = NULL;
unsigned char *sstr = NULL;
pbe = PBEPARAM_new();
if (pbe == NULL) {
ASN1err(ASN1_F_PKCS5_PBE_SET0_ALGOR, ERR_R_MALLOC_FAILURE);
goto err;
}
if (iter <= 0)
iter = PKCS5_DEFAULT_ITER;
if (!ASN1_INTEGER_set(pbe->iter, iter)) {
ASN1err(ASN1_F_PKCS5_PBE_SET0_ALGOR, ERR_R_MALLOC_FAILURE);
goto err;
}
if (!saltlen)
saltlen = PKCS5_SALT_LEN;
sstr = OPENSSL_malloc(saltlen);
if (sstr == NULL) {
ASN1err(ASN1_F_PKCS5_PBE_SET0_ALGOR, ERR_R_MALLOC_FAILURE);
goto err;
}
if (salt)
memcpy(sstr, salt, saltlen);
else if (RAND_bytes(sstr, saltlen) <= 0)
goto err;
ASN1_STRING_set0(pbe->salt, sstr, saltlen);
sstr = NULL;
if (!ASN1_item_pack(pbe, ASN1_ITEM_rptr(PBEPARAM), &pbe_str)) {
ASN1err(ASN1_F_PKCS5_PBE_SET0_ALGOR, ERR_R_MALLOC_FAILURE);
goto err;
}
PBEPARAM_free(pbe);
pbe = NULL;
if (X509_ALGOR_set0(algor, OBJ_nid2obj(alg), V_ASN1_SEQUENCE, pbe_str))
return 1;
err:
OPENSSL_free(sstr);
PBEPARAM_free(pbe);
ASN1_STRING_free(pbe_str);
return 0;
}
/* Return an algorithm identifier for a PKCS#5 PBE algorithm */
X509_ALGOR *PKCS5_pbe_set(int alg, int iter,
const unsigned char *salt, int saltlen)
{
X509_ALGOR *ret;
ret = X509_ALGOR_new();
if (ret == NULL) {
ASN1err(ASN1_F_PKCS5_PBE_SET, ERR_R_MALLOC_FAILURE);
return NULL;
}
if (PKCS5_pbe_set0_algor(ret, alg, iter, salt, saltlen))
return ret;
X509_ALGOR_free(ret);
return NULL;
}

View file

@ -0,0 +1,221 @@
/*
* Copyright 1999-2018 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <stdio.h>
#include "internal/cryptlib.h"
#include <openssl/asn1t.h>
#include <openssl/x509.h>
#include <openssl/rand.h>
/* PKCS#5 v2.0 password based encryption structures */
ASN1_SEQUENCE(PBE2PARAM) = {
ASN1_SIMPLE(PBE2PARAM, keyfunc, X509_ALGOR),
ASN1_SIMPLE(PBE2PARAM, encryption, X509_ALGOR)
} ASN1_SEQUENCE_END(PBE2PARAM)
IMPLEMENT_ASN1_FUNCTIONS(PBE2PARAM)
ASN1_SEQUENCE(PBKDF2PARAM) = {
ASN1_SIMPLE(PBKDF2PARAM, salt, ASN1_ANY),
ASN1_SIMPLE(PBKDF2PARAM, iter, ASN1_INTEGER),
ASN1_OPT(PBKDF2PARAM, keylength, ASN1_INTEGER),
ASN1_OPT(PBKDF2PARAM, prf, X509_ALGOR)
} ASN1_SEQUENCE_END(PBKDF2PARAM)
IMPLEMENT_ASN1_FUNCTIONS(PBKDF2PARAM)
/*
* Return an algorithm identifier for a PKCS#5 v2.0 PBE algorithm: yes I know
* this is horrible! Extended version to allow application supplied PRF NID
* and IV.
*/
X509_ALGOR *PKCS5_pbe2_set_iv(const EVP_CIPHER *cipher, int iter,
unsigned char *salt, int saltlen,
unsigned char *aiv, int prf_nid)
{
X509_ALGOR *scheme = NULL, *ret = NULL;
int alg_nid, keylen;
EVP_CIPHER_CTX *ctx = NULL;
unsigned char iv[EVP_MAX_IV_LENGTH];
PBE2PARAM *pbe2 = NULL;
alg_nid = EVP_CIPHER_type(cipher);
if (alg_nid == NID_undef) {
ASN1err(ASN1_F_PKCS5_PBE2_SET_IV,
ASN1_R_CIPHER_HAS_NO_OBJECT_IDENTIFIER);
goto err;
}
if ((pbe2 = PBE2PARAM_new()) == NULL)
goto merr;
/* Setup the AlgorithmIdentifier for the encryption scheme */
scheme = pbe2->encryption;
scheme->algorithm = OBJ_nid2obj(alg_nid);
if ((scheme->parameter = ASN1_TYPE_new()) == NULL)
goto merr;
/* Create random IV */
if (EVP_CIPHER_iv_length(cipher)) {
if (aiv)
memcpy(iv, aiv, EVP_CIPHER_iv_length(cipher));
else if (RAND_bytes(iv, EVP_CIPHER_iv_length(cipher)) <= 0)
goto err;
}
ctx = EVP_CIPHER_CTX_new();
if (ctx == NULL)
goto merr;
/* Dummy cipherinit to just setup the IV, and PRF */
if (!EVP_CipherInit_ex(ctx, cipher, NULL, NULL, iv, 0))
goto err;
if (EVP_CIPHER_param_to_asn1(ctx, scheme->parameter) <= 0) {
ASN1err(ASN1_F_PKCS5_PBE2_SET_IV, ASN1_R_ERROR_SETTING_CIPHER_PARAMS);
goto err;
}
/*
* If prf NID unspecified see if cipher has a preference. An error is OK
* here: just means use default PRF.
*/
if ((prf_nid == -1) &&
EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_PBE_PRF_NID, 0, &prf_nid) <= 0) {
ERR_clear_error();
prf_nid = NID_hmacWithSHA256;
}
EVP_CIPHER_CTX_free(ctx);
ctx = NULL;
/* If its RC2 then we'd better setup the key length */
if (alg_nid == NID_rc2_cbc)
keylen = EVP_CIPHER_key_length(cipher);
else
keylen = -1;
/* Setup keyfunc */
X509_ALGOR_free(pbe2->keyfunc);
pbe2->keyfunc = PKCS5_pbkdf2_set(iter, salt, saltlen, prf_nid, keylen);
if (!pbe2->keyfunc)
goto merr;
/* Now set up top level AlgorithmIdentifier */
if ((ret = X509_ALGOR_new()) == NULL)
goto merr;
ret->algorithm = OBJ_nid2obj(NID_pbes2);
/* Encode PBE2PARAM into parameter */
if (!ASN1_TYPE_pack_sequence(ASN1_ITEM_rptr(PBE2PARAM), pbe2,
&ret->parameter))
goto merr;
PBE2PARAM_free(pbe2);
pbe2 = NULL;
return ret;
merr:
ASN1err(ASN1_F_PKCS5_PBE2_SET_IV, ERR_R_MALLOC_FAILURE);
err:
EVP_CIPHER_CTX_free(ctx);
PBE2PARAM_free(pbe2);
/* Note 'scheme' is freed as part of pbe2 */
X509_ALGOR_free(ret);
return NULL;
}
X509_ALGOR *PKCS5_pbe2_set(const EVP_CIPHER *cipher, int iter,
unsigned char *salt, int saltlen)
{
return PKCS5_pbe2_set_iv(cipher, iter, salt, saltlen, NULL, -1);
}
X509_ALGOR *PKCS5_pbkdf2_set(int iter, unsigned char *salt, int saltlen,
int prf_nid, int keylen)
{
X509_ALGOR *keyfunc = NULL;
PBKDF2PARAM *kdf = NULL;
ASN1_OCTET_STRING *osalt = NULL;
if ((kdf = PBKDF2PARAM_new()) == NULL)
goto merr;
if ((osalt = ASN1_OCTET_STRING_new()) == NULL)
goto merr;
kdf->salt->value.octet_string = osalt;
kdf->salt->type = V_ASN1_OCTET_STRING;
if (saltlen == 0)
saltlen = PKCS5_SALT_LEN;
if ((osalt->data = OPENSSL_malloc(saltlen)) == NULL)
goto merr;
osalt->length = saltlen;
if (salt)
memcpy(osalt->data, salt, saltlen);
else if (RAND_bytes(osalt->data, saltlen) <= 0)
goto merr;
if (iter <= 0)
iter = PKCS5_DEFAULT_ITER;
if (!ASN1_INTEGER_set(kdf->iter, iter))
goto merr;
/* If have a key len set it up */
if (keylen > 0) {
if ((kdf->keylength = ASN1_INTEGER_new()) == NULL)
goto merr;
if (!ASN1_INTEGER_set(kdf->keylength, keylen))
goto merr;
}
/* prf can stay NULL if we are using hmacWithSHA1 */
if (prf_nid > 0 && prf_nid != NID_hmacWithSHA1) {
kdf->prf = X509_ALGOR_new();
if (kdf->prf == NULL)
goto merr;
X509_ALGOR_set0(kdf->prf, OBJ_nid2obj(prf_nid), V_ASN1_NULL, NULL);
}
/* Finally setup the keyfunc structure */
keyfunc = X509_ALGOR_new();
if (keyfunc == NULL)
goto merr;
keyfunc->algorithm = OBJ_nid2obj(NID_id_pbkdf2);
/* Encode PBKDF2PARAM into parameter of pbe2 */
if (!ASN1_TYPE_pack_sequence(ASN1_ITEM_rptr(PBKDF2PARAM), kdf,
&keyfunc->parameter))
goto merr;
PBKDF2PARAM_free(kdf);
return keyfunc;
merr:
ASN1err(ASN1_F_PKCS5_PBKDF2_SET, ERR_R_MALLOC_FAILURE);
PBKDF2PARAM_free(kdf);
X509_ALGOR_free(keyfunc);
return NULL;
}

View file

@ -0,0 +1,274 @@
/*
* Copyright 2015-2018 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <stdio.h>
#include "internal/cryptlib.h"
#include <openssl/asn1t.h>
#include <openssl/err.h>
#include <openssl/evp.h>
#include <openssl/x509.h>
#include <openssl/rand.h>
#ifndef OPENSSL_NO_SCRYPT
/* PKCS#5 scrypt password based encryption structures */
ASN1_SEQUENCE(SCRYPT_PARAMS) = {
ASN1_SIMPLE(SCRYPT_PARAMS, salt, ASN1_OCTET_STRING),
ASN1_SIMPLE(SCRYPT_PARAMS, costParameter, ASN1_INTEGER),
ASN1_SIMPLE(SCRYPT_PARAMS, blockSize, ASN1_INTEGER),
ASN1_SIMPLE(SCRYPT_PARAMS, parallelizationParameter, ASN1_INTEGER),
ASN1_OPT(SCRYPT_PARAMS, keyLength, ASN1_INTEGER),
} ASN1_SEQUENCE_END(SCRYPT_PARAMS)
IMPLEMENT_ASN1_FUNCTIONS(SCRYPT_PARAMS)
static X509_ALGOR *pkcs5_scrypt_set(const unsigned char *salt, size_t saltlen,
size_t keylen, uint64_t N, uint64_t r,
uint64_t p);
/*
* Return an algorithm identifier for a PKCS#5 v2.0 PBE algorithm using scrypt
*/
X509_ALGOR *PKCS5_pbe2_set_scrypt(const EVP_CIPHER *cipher,
const unsigned char *salt, int saltlen,
unsigned char *aiv, uint64_t N, uint64_t r,
uint64_t p)
{
X509_ALGOR *scheme = NULL, *ret = NULL;
int alg_nid;
size_t keylen = 0;
EVP_CIPHER_CTX *ctx = NULL;
unsigned char iv[EVP_MAX_IV_LENGTH];
PBE2PARAM *pbe2 = NULL;
if (!cipher) {
ASN1err(ASN1_F_PKCS5_PBE2_SET_SCRYPT, ERR_R_PASSED_NULL_PARAMETER);
goto err;
}
if (EVP_PBE_scrypt(NULL, 0, NULL, 0, N, r, p, 0, NULL, 0) == 0) {
ASN1err(ASN1_F_PKCS5_PBE2_SET_SCRYPT,
ASN1_R_INVALID_SCRYPT_PARAMETERS);
goto err;
}
alg_nid = EVP_CIPHER_type(cipher);
if (alg_nid == NID_undef) {
ASN1err(ASN1_F_PKCS5_PBE2_SET_SCRYPT,
ASN1_R_CIPHER_HAS_NO_OBJECT_IDENTIFIER);
goto err;
}
pbe2 = PBE2PARAM_new();
if (pbe2 == NULL)
goto merr;
/* Setup the AlgorithmIdentifier for the encryption scheme */
scheme = pbe2->encryption;
scheme->algorithm = OBJ_nid2obj(alg_nid);
scheme->parameter = ASN1_TYPE_new();
if (scheme->parameter == NULL)
goto merr;
/* Create random IV */
if (EVP_CIPHER_iv_length(cipher)) {
if (aiv)
memcpy(iv, aiv, EVP_CIPHER_iv_length(cipher));
else if (RAND_bytes(iv, EVP_CIPHER_iv_length(cipher)) <= 0)
goto err;
}
ctx = EVP_CIPHER_CTX_new();
if (ctx == NULL)
goto merr;
/* Dummy cipherinit to just setup the IV */
if (EVP_CipherInit_ex(ctx, cipher, NULL, NULL, iv, 0) == 0)
goto err;
if (EVP_CIPHER_param_to_asn1(ctx, scheme->parameter) <= 0) {
ASN1err(ASN1_F_PKCS5_PBE2_SET_SCRYPT,
ASN1_R_ERROR_SETTING_CIPHER_PARAMS);
goto err;
}
EVP_CIPHER_CTX_free(ctx);
ctx = NULL;
/* If its RC2 then we'd better setup the key length */
if (alg_nid == NID_rc2_cbc)
keylen = EVP_CIPHER_key_length(cipher);
/* Setup keyfunc */
X509_ALGOR_free(pbe2->keyfunc);
pbe2->keyfunc = pkcs5_scrypt_set(salt, saltlen, keylen, N, r, p);
if (pbe2->keyfunc == NULL)
goto merr;
/* Now set up top level AlgorithmIdentifier */
ret = X509_ALGOR_new();
if (ret == NULL)
goto merr;
ret->algorithm = OBJ_nid2obj(NID_pbes2);
/* Encode PBE2PARAM into parameter */
if (ASN1_TYPE_pack_sequence(ASN1_ITEM_rptr(PBE2PARAM), pbe2,
&ret->parameter) == NULL)
goto merr;
PBE2PARAM_free(pbe2);
pbe2 = NULL;
return ret;
merr:
ASN1err(ASN1_F_PKCS5_PBE2_SET_SCRYPT, ERR_R_MALLOC_FAILURE);
err:
PBE2PARAM_free(pbe2);
X509_ALGOR_free(ret);
EVP_CIPHER_CTX_free(ctx);
return NULL;
}
static X509_ALGOR *pkcs5_scrypt_set(const unsigned char *salt, size_t saltlen,
size_t keylen, uint64_t N, uint64_t r,
uint64_t p)
{
X509_ALGOR *keyfunc = NULL;
SCRYPT_PARAMS *sparam = SCRYPT_PARAMS_new();
if (sparam == NULL)
goto merr;
if (!saltlen)
saltlen = PKCS5_SALT_LEN;
/* This will either copy salt or grow the buffer */
if (ASN1_STRING_set(sparam->salt, salt, saltlen) == 0)
goto merr;
if (salt == NULL && RAND_bytes(sparam->salt->data, saltlen) <= 0)
goto err;
if (ASN1_INTEGER_set_uint64(sparam->costParameter, N) == 0)
goto merr;
if (ASN1_INTEGER_set_uint64(sparam->blockSize, r) == 0)
goto merr;
if (ASN1_INTEGER_set_uint64(sparam->parallelizationParameter, p) == 0)
goto merr;
/* If have a key len set it up */
if (keylen > 0) {
sparam->keyLength = ASN1_INTEGER_new();
if (sparam->keyLength == NULL)
goto merr;
if (ASN1_INTEGER_set_int64(sparam->keyLength, keylen) == 0)
goto merr;
}
/* Finally setup the keyfunc structure */
keyfunc = X509_ALGOR_new();
if (keyfunc == NULL)
goto merr;
keyfunc->algorithm = OBJ_nid2obj(NID_id_scrypt);
/* Encode SCRYPT_PARAMS into parameter of pbe2 */
if (ASN1_TYPE_pack_sequence(ASN1_ITEM_rptr(SCRYPT_PARAMS), sparam,
&keyfunc->parameter) == NULL)
goto merr;
SCRYPT_PARAMS_free(sparam);
return keyfunc;
merr:
ASN1err(ASN1_F_PKCS5_SCRYPT_SET, ERR_R_MALLOC_FAILURE);
err:
SCRYPT_PARAMS_free(sparam);
X509_ALGOR_free(keyfunc);
return NULL;
}
int PKCS5_v2_scrypt_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass,
int passlen, ASN1_TYPE *param,
const EVP_CIPHER *c, const EVP_MD *md, int en_de)
{
unsigned char *salt, key[EVP_MAX_KEY_LENGTH];
uint64_t p, r, N;
size_t saltlen;
size_t keylen = 0;
int rv = 0;
SCRYPT_PARAMS *sparam = NULL;
if (EVP_CIPHER_CTX_cipher(ctx) == NULL) {
EVPerr(EVP_F_PKCS5_V2_SCRYPT_KEYIVGEN, EVP_R_NO_CIPHER_SET);
goto err;
}
/* Decode parameter */
sparam = ASN1_TYPE_unpack_sequence(ASN1_ITEM_rptr(SCRYPT_PARAMS), param);
if (sparam == NULL) {
EVPerr(EVP_F_PKCS5_V2_SCRYPT_KEYIVGEN, EVP_R_DECODE_ERROR);
goto err;
}
keylen = EVP_CIPHER_CTX_key_length(ctx);
/* Now check the parameters of sparam */
if (sparam->keyLength) {
uint64_t spkeylen;
if ((ASN1_INTEGER_get_uint64(&spkeylen, sparam->keyLength) == 0)
|| (spkeylen != keylen)) {
EVPerr(EVP_F_PKCS5_V2_SCRYPT_KEYIVGEN,
EVP_R_UNSUPPORTED_KEYLENGTH);
goto err;
}
}
/* Check all parameters fit in uint64_t and are acceptable to scrypt */
if (ASN1_INTEGER_get_uint64(&N, sparam->costParameter) == 0
|| ASN1_INTEGER_get_uint64(&r, sparam->blockSize) == 0
|| ASN1_INTEGER_get_uint64(&p, sparam->parallelizationParameter) == 0
|| EVP_PBE_scrypt(NULL, 0, NULL, 0, N, r, p, 0, NULL, 0) == 0) {
EVPerr(EVP_F_PKCS5_V2_SCRYPT_KEYIVGEN,
EVP_R_ILLEGAL_SCRYPT_PARAMETERS);
goto err;
}
/* it seems that its all OK */
salt = sparam->salt->data;
saltlen = sparam->salt->length;
if (EVP_PBE_scrypt(pass, passlen, salt, saltlen, N, r, p, 0, key, keylen)
== 0)
goto err;
rv = EVP_CipherInit_ex(ctx, NULL, NULL, key, NULL, en_de);
err:
if (keylen)
OPENSSL_cleanse(key, keylen);
SCRYPT_PARAMS_free(sparam);
return rv;
}
#endif /* OPENSSL_NO_SCRYPT */

View file

@ -0,0 +1,80 @@
/*
* Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <stdio.h>
#include "internal/cryptlib.h"
#include <openssl/asn1t.h>
#include <openssl/x509.h>
#include "internal/x509_int.h"
/* Minor tweak to operation: zero private key data */
static int pkey_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
void *exarg)
{
/* Since the structure must still be valid use ASN1_OP_FREE_PRE */
if (operation == ASN1_OP_FREE_PRE) {
PKCS8_PRIV_KEY_INFO *key = (PKCS8_PRIV_KEY_INFO *)*pval;
if (key->pkey)
OPENSSL_cleanse(key->pkey->data, key->pkey->length);
}
return 1;
}
ASN1_SEQUENCE_cb(PKCS8_PRIV_KEY_INFO, pkey_cb) = {
ASN1_SIMPLE(PKCS8_PRIV_KEY_INFO, version, ASN1_INTEGER),
ASN1_SIMPLE(PKCS8_PRIV_KEY_INFO, pkeyalg, X509_ALGOR),
ASN1_SIMPLE(PKCS8_PRIV_KEY_INFO, pkey, ASN1_OCTET_STRING),
ASN1_IMP_SET_OF_OPT(PKCS8_PRIV_KEY_INFO, attributes, X509_ATTRIBUTE, 0)
} ASN1_SEQUENCE_END_cb(PKCS8_PRIV_KEY_INFO, PKCS8_PRIV_KEY_INFO)
IMPLEMENT_ASN1_FUNCTIONS(PKCS8_PRIV_KEY_INFO)
int PKCS8_pkey_set0(PKCS8_PRIV_KEY_INFO *priv, ASN1_OBJECT *aobj,
int version,
int ptype, void *pval, unsigned char *penc, int penclen)
{
if (version >= 0) {
if (!ASN1_INTEGER_set(priv->version, version))
return 0;
}
if (!X509_ALGOR_set0(priv->pkeyalg, aobj, ptype, pval))
return 0;
if (penc)
ASN1_STRING_set0(priv->pkey, penc, penclen);
return 1;
}
int PKCS8_pkey_get0(const ASN1_OBJECT **ppkalg,
const unsigned char **pk, int *ppklen,
const X509_ALGOR **pa, const PKCS8_PRIV_KEY_INFO *p8)
{
if (ppkalg)
*ppkalg = p8->pkeyalg->algorithm;
if (pk) {
*pk = ASN1_STRING_get0_data(p8->pkey);
*ppklen = ASN1_STRING_length(p8->pkey);
}
if (pa)
*pa = p8->pkeyalg;
return 1;
}
const STACK_OF(X509_ATTRIBUTE) *
PKCS8_pkey_get0_attrs(const PKCS8_PRIV_KEY_INFO *p8)
{
return p8->attributes;
}
int PKCS8_pkey_add1_attr_by_NID(PKCS8_PRIV_KEY_INFO *p8, int nid, int type,
const unsigned char *bytes, int len)
{
if (X509at_add1_attr_by_NID(&p8->attributes, nid, type, bytes, len) != NULL)
return 1;
return 0;
}

View file

@ -0,0 +1,61 @@
/*
* Copyright 2006-2018 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
/*
* This table MUST be kept in ascending order of the NID each method
* represents (corresponding to the pkey_id field) as OBJ_bsearch
* is used to search it.
*/
static const EVP_PKEY_ASN1_METHOD *standard_methods[] = {
#ifndef OPENSSL_NO_RSA
&rsa_asn1_meths[0],
&rsa_asn1_meths[1],
#endif
#ifndef OPENSSL_NO_DH
&dh_asn1_meth,
#endif
#ifndef OPENSSL_NO_DSA
&dsa_asn1_meths[0],
&dsa_asn1_meths[1],
&dsa_asn1_meths[2],
&dsa_asn1_meths[3],
&dsa_asn1_meths[4],
#endif
#ifndef OPENSSL_NO_EC
&eckey_asn1_meth,
#endif
&hmac_asn1_meth,
#ifndef OPENSSL_NO_CMAC
&cmac_asn1_meth,
#endif
#ifndef OPENSSL_NO_RSA
&rsa_pss_asn1_meth,
#endif
#ifndef OPENSSL_NO_DH
&dhx_asn1_meth,
#endif
#ifndef OPENSSL_NO_EC
&ecx25519_asn1_meth,
&ecx448_asn1_meth,
#endif
#ifndef OPENSSL_NO_POLY1305
&poly1305_asn1_meth,
#endif
#ifndef OPENSSL_NO_SIPHASH
&siphash_asn1_meth,
#endif
#ifndef OPENSSL_NO_EC
&ed25519_asn1_meth,
&ed448_asn1_meth,
#endif
#ifndef OPENSSL_NO_SM2
&sm2_asn1_meth,
#endif
};

View file

@ -0,0 +1,56 @@
/*
* Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <stdio.h>
#include "internal/cryptlib.h"
#include <openssl/conf.h>
#include <openssl/x509v3.h>
int ASN1_BIT_STRING_name_print(BIO *out, ASN1_BIT_STRING *bs,
BIT_STRING_BITNAME *tbl, int indent)
{
BIT_STRING_BITNAME *bnam;
char first = 1;
BIO_printf(out, "%*s", indent, "");
for (bnam = tbl; bnam->lname; bnam++) {
if (ASN1_BIT_STRING_get_bit(bs, bnam->bitnum)) {
if (!first)
BIO_puts(out, ", ");
BIO_puts(out, bnam->lname);
first = 0;
}
}
BIO_puts(out, "\n");
return 1;
}
int ASN1_BIT_STRING_set_asc(ASN1_BIT_STRING *bs, const char *name, int value,
BIT_STRING_BITNAME *tbl)
{
int bitnum;
bitnum = ASN1_BIT_STRING_num_asc(name, tbl);
if (bitnum < 0)
return 0;
if (bs) {
if (!ASN1_BIT_STRING_set_bit(bs, bitnum, value))
return 0;
}
return 1;
}
int ASN1_BIT_STRING_num_asc(const char *name, BIT_STRING_BITNAME *tbl)
{
BIT_STRING_BITNAME *bnam;
for (bnam = tbl; bnam->lname; bnam++) {
if ((strcmp(bnam->sname, name) == 0)
|| (strcmp(bnam->lname, name) == 0))
return bnam->bitnum;
}
return -1;
}

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