adding pods method of package managing
This commit is contained in:
Generated
+251
@@ -0,0 +1,251 @@
|
||||
BoringSSL is a fork of OpenSSL. As such, large parts of it fall under OpenSSL
|
||||
licensing. Files that are completely new have a Google copyright and an ISC
|
||||
license. This license is reproduced at the bottom of this file.
|
||||
|
||||
Contributors to BoringSSL are required to follow the CLA rules for Chromium:
|
||||
https://cla.developers.google.com/clas
|
||||
|
||||
Files in third_party/ have their own licenses, as described therein. The MIT
|
||||
license, for third_party/fiat, which, unlike other third_party directories, is
|
||||
compiled into non-test libraries, is included below.
|
||||
|
||||
The OpenSSL toolkit stays under a dual license, i.e. both the conditions of the
|
||||
OpenSSL License and the original SSLeay license apply to the toolkit. See below
|
||||
for the actual license texts. Actually both licenses are BSD-style Open Source
|
||||
licenses. In case of any license issues related to OpenSSL please contact
|
||||
[email protected].
|
||||
|
||||
The following are Google-internal bug numbers where explicit permission from
|
||||
some authors is recorded for use of their work. (This is purely for our own
|
||||
record keeping.)
|
||||
27287199
|
||||
27287880
|
||||
27287883
|
||||
|
||||
OpenSSL License
|
||||
---------------
|
||||
|
||||
/* ====================================================================
|
||||
* Copyright (c) 1998-2011 The OpenSSL Project. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* 3. All advertising materials mentioning features or use of this
|
||||
* software must display the following acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
|
||||
*
|
||||
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
|
||||
* endorse or promote products derived from this software without
|
||||
* prior written permission. For written permission, please contact
|
||||
* [email protected].
|
||||
*
|
||||
* 5. Products derived from this software may not be called "OpenSSL"
|
||||
* nor may "OpenSSL" appear in their names without prior written
|
||||
* permission of the OpenSSL Project.
|
||||
*
|
||||
* 6. Redistributions of any form whatsoever must retain the following
|
||||
* acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit (http://www.openssl.org/)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
|
||||
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
|
||||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ====================================================================
|
||||
*
|
||||
* This product includes cryptographic software written by Eric Young
|
||||
* ([email protected]). This product includes software written by Tim
|
||||
* Hudson ([email protected]).
|
||||
*
|
||||
*/
|
||||
|
||||
Original SSLeay License
|
||||
-----------------------
|
||||
|
||||
/* Copyright (C) 1995-1998 Eric Young ([email protected])
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young ([email protected]).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson ([email protected]).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young ([email protected])"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson ([email protected])"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.]
|
||||
*/
|
||||
|
||||
|
||||
ISC license used for completely new code in BoringSSL:
|
||||
|
||||
/* Copyright (c) 2015, Google Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
||||
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
|
||||
|
||||
|
||||
The code in third_party/fiat carries the MIT license:
|
||||
|
||||
Copyright (c) 2015-2016 the fiat-crypto authors (see
|
||||
https://github.com/mit-plv/fiat-crypto/blob/master/AUTHORS).
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
|
||||
Licenses for support code
|
||||
-------------------------
|
||||
|
||||
Parts of the TLS test suite are under the Go license. This code is not included
|
||||
in BoringSSL (i.e. libcrypto and libssl) when compiled, however, so
|
||||
distributing code linked against BoringSSL does not trigger this license:
|
||||
|
||||
Copyright (c) 2009 The Go Authors. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* 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.
|
||||
* Neither the name of Google Inc. nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
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.
|
||||
|
||||
|
||||
BoringSSL uses the Chromium test infrastructure to run a continuous build,
|
||||
trybots etc. The scripts which manage this, and the script for generating build
|
||||
metadata, are under the Chromium license. Distributing code linked against
|
||||
BoringSSL does not trigger this license.
|
||||
|
||||
Copyright 2015 The Chromium Authors. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* 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.
|
||||
* Neither the name of Google Inc. nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
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.
|
||||
Generated
+1407
File diff suppressed because it is too large
Load Diff
Generated
+1407
File diff suppressed because it is too large
Load Diff
+271
@@ -0,0 +1,271 @@
|
||||
/* Copyright (C) 1995-1998 Eric Young ([email protected])
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young ([email protected]).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson ([email protected]).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young ([email protected])"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson ([email protected])"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.] */
|
||||
|
||||
#include <openssl_grpc/asn1.h>
|
||||
|
||||
#include <limits.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <openssl_grpc/err.h>
|
||||
#include <openssl_grpc/mem.h>
|
||||
|
||||
#include "../internal.h"
|
||||
|
||||
|
||||
int ASN1_BIT_STRING_set(ASN1_BIT_STRING *x, unsigned char *d, int len)
|
||||
{
|
||||
return M_ASN1_BIT_STRING_set(x, d, len);
|
||||
}
|
||||
|
||||
int i2c_ASN1_BIT_STRING(ASN1_BIT_STRING *a, unsigned char **pp)
|
||||
{
|
||||
int ret, j, bits, len;
|
||||
unsigned char *p, *d;
|
||||
|
||||
if (a == NULL)
|
||||
return (0);
|
||||
|
||||
len = a->length;
|
||||
|
||||
if (len > 0) {
|
||||
if (a->flags & ASN1_STRING_FLAG_BITS_LEFT) {
|
||||
bits = (int)a->flags & 0x07;
|
||||
} else {
|
||||
for (; len > 0; len--) {
|
||||
if (a->data[len - 1])
|
||||
break;
|
||||
}
|
||||
j = a->data[len - 1];
|
||||
if (j & 0x01)
|
||||
bits = 0;
|
||||
else if (j & 0x02)
|
||||
bits = 1;
|
||||
else if (j & 0x04)
|
||||
bits = 2;
|
||||
else if (j & 0x08)
|
||||
bits = 3;
|
||||
else if (j & 0x10)
|
||||
bits = 4;
|
||||
else if (j & 0x20)
|
||||
bits = 5;
|
||||
else if (j & 0x40)
|
||||
bits = 6;
|
||||
else if (j & 0x80)
|
||||
bits = 7;
|
||||
else
|
||||
bits = 0; /* should not happen */
|
||||
}
|
||||
} else
|
||||
bits = 0;
|
||||
|
||||
ret = 1 + len;
|
||||
if (pp == NULL)
|
||||
return (ret);
|
||||
|
||||
p = *pp;
|
||||
|
||||
*(p++) = (unsigned char)bits;
|
||||
d = a->data;
|
||||
OPENSSL_memcpy(p, d, len);
|
||||
p += len;
|
||||
if (len > 0)
|
||||
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 padding;
|
||||
|
||||
if (len < 1) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_STRING_TOO_SHORT);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (len > INT_MAX) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_STRING_TOO_LONG);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if ((a == NULL) || ((*a) == NULL)) {
|
||||
if ((ret = M_ASN1_BIT_STRING_new()) == NULL)
|
||||
return (NULL);
|
||||
} else
|
||||
ret = (*a);
|
||||
|
||||
p = *pp;
|
||||
padding = *(p++);
|
||||
if (padding > 7) {
|
||||
OPENSSL_PUT_ERROR(ASN1, 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 | padding); /* set */
|
||||
|
||||
if (len-- > 1) { /* using one because of the bits left byte */
|
||||
s = (unsigned char *)OPENSSL_malloc((int)len);
|
||||
if (s == NULL) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
OPENSSL_memcpy(s, p, (int)len);
|
||||
s[len - 1] &= (0xff << padding);
|
||||
p += len;
|
||||
} else
|
||||
s = NULL;
|
||||
|
||||
ret->length = (int)len;
|
||||
if (ret->data != NULL)
|
||||
OPENSSL_free(ret->data);
|
||||
ret->data = s;
|
||||
ret->type = V_ASN1_BIT_STRING;
|
||||
if (a != NULL)
|
||||
(*a) = ret;
|
||||
*pp = p;
|
||||
return (ret);
|
||||
err:
|
||||
if ((ret != NULL) && ((a == NULL) || (*a != ret)))
|
||||
M_ASN1_BIT_STRING_free(ret);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* These next 2 functions from Goetz Babin-Ebell <[email protected]>
|
||||
*/
|
||||
int ASN1_BIT_STRING_set_bit(ASN1_BIT_STRING *a, int n, int value)
|
||||
{
|
||||
int w, v, iv;
|
||||
unsigned char *c;
|
||||
|
||||
w = n / 8;
|
||||
v = 1 << (7 - (n & 0x07));
|
||||
iv = ~v;
|
||||
if (!value)
|
||||
v = 0;
|
||||
|
||||
if (a == NULL)
|
||||
return 0;
|
||||
|
||||
a->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07); /* clear, set on write */
|
||||
|
||||
if ((a->length < (w + 1)) || (a->data == NULL)) {
|
||||
if (!value)
|
||||
return (1); /* Don't need to set */
|
||||
if (a->data == NULL)
|
||||
c = (unsigned char *)OPENSSL_malloc(w + 1);
|
||||
else
|
||||
c = (unsigned char *)OPENSSL_realloc(a->data, w + 1);
|
||||
if (c == NULL) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
if (w + 1 - a->length > 0)
|
||||
OPENSSL_memset(c + a->length, 0, w + 1 - a->length);
|
||||
a->data = c;
|
||||
a->length = w + 1;
|
||||
}
|
||||
a->data[w] = ((a->data[w]) & iv) | v;
|
||||
while ((a->length > 0) && (a->data[a->length - 1] == 0))
|
||||
a->length--;
|
||||
return (1);
|
||||
}
|
||||
|
||||
int ASN1_BIT_STRING_get_bit(ASN1_BIT_STRING *a, int n)
|
||||
{
|
||||
int w, v;
|
||||
|
||||
w = n / 8;
|
||||
v = 1 << (7 - (n & 0x07));
|
||||
if ((a == NULL) || (a->length < (w + 1)) || (a->data == NULL))
|
||||
return (0);
|
||||
return ((a->data[w] & v) != 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Checks if the given bit string contains only bits specified by
|
||||
* the flags vector. Returns 0 if there is at least one bit set in 'a'
|
||||
* which is not specified in 'flags', 1 otherwise.
|
||||
* 'len' is the length of 'flags'.
|
||||
*/
|
||||
int ASN1_BIT_STRING_check(ASN1_BIT_STRING *a,
|
||||
unsigned char *flags, int flags_len)
|
||||
{
|
||||
int i, ok;
|
||||
/* Check if there is one bit set at all. */
|
||||
if (!a || !a->data)
|
||||
return 1;
|
||||
|
||||
/*
|
||||
* Check each byte of the internal representation of the bit string.
|
||||
*/
|
||||
ok = 1;
|
||||
for (i = 0; i < a->length && ok; ++i) {
|
||||
unsigned char mask = i < flags_len ? ~flags[i] : 0xff;
|
||||
/* We are done if there is an unneeded bit set. */
|
||||
ok = (a->data[i] & mask) == 0;
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
@@ -0,0 +1,271 @@
|
||||
/* Copyright (C) 1995-1998 Eric Young ([email protected])
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young ([email protected]).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson ([email protected]).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young ([email protected])"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson ([email protected])"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.] */
|
||||
|
||||
#include <openssl/asn1.h>
|
||||
|
||||
#include <limits.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/mem.h>
|
||||
|
||||
#include "../internal.h"
|
||||
|
||||
|
||||
int ASN1_BIT_STRING_set(ASN1_BIT_STRING *x, unsigned char *d, int len)
|
||||
{
|
||||
return M_ASN1_BIT_STRING_set(x, d, len);
|
||||
}
|
||||
|
||||
int i2c_ASN1_BIT_STRING(ASN1_BIT_STRING *a, unsigned char **pp)
|
||||
{
|
||||
int ret, j, bits, len;
|
||||
unsigned char *p, *d;
|
||||
|
||||
if (a == NULL)
|
||||
return (0);
|
||||
|
||||
len = a->length;
|
||||
|
||||
if (len > 0) {
|
||||
if (a->flags & ASN1_STRING_FLAG_BITS_LEFT) {
|
||||
bits = (int)a->flags & 0x07;
|
||||
} else {
|
||||
for (; len > 0; len--) {
|
||||
if (a->data[len - 1])
|
||||
break;
|
||||
}
|
||||
j = a->data[len - 1];
|
||||
if (j & 0x01)
|
||||
bits = 0;
|
||||
else if (j & 0x02)
|
||||
bits = 1;
|
||||
else if (j & 0x04)
|
||||
bits = 2;
|
||||
else if (j & 0x08)
|
||||
bits = 3;
|
||||
else if (j & 0x10)
|
||||
bits = 4;
|
||||
else if (j & 0x20)
|
||||
bits = 5;
|
||||
else if (j & 0x40)
|
||||
bits = 6;
|
||||
else if (j & 0x80)
|
||||
bits = 7;
|
||||
else
|
||||
bits = 0; /* should not happen */
|
||||
}
|
||||
} else
|
||||
bits = 0;
|
||||
|
||||
ret = 1 + len;
|
||||
if (pp == NULL)
|
||||
return (ret);
|
||||
|
||||
p = *pp;
|
||||
|
||||
*(p++) = (unsigned char)bits;
|
||||
d = a->data;
|
||||
OPENSSL_memcpy(p, d, len);
|
||||
p += len;
|
||||
if (len > 0)
|
||||
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 padding;
|
||||
|
||||
if (len < 1) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_STRING_TOO_SHORT);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (len > INT_MAX) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_STRING_TOO_LONG);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if ((a == NULL) || ((*a) == NULL)) {
|
||||
if ((ret = M_ASN1_BIT_STRING_new()) == NULL)
|
||||
return (NULL);
|
||||
} else
|
||||
ret = (*a);
|
||||
|
||||
p = *pp;
|
||||
padding = *(p++);
|
||||
if (padding > 7) {
|
||||
OPENSSL_PUT_ERROR(ASN1, 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 | padding); /* set */
|
||||
|
||||
if (len-- > 1) { /* using one because of the bits left byte */
|
||||
s = (unsigned char *)OPENSSL_malloc((int)len);
|
||||
if (s == NULL) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
OPENSSL_memcpy(s, p, (int)len);
|
||||
s[len - 1] &= (0xff << padding);
|
||||
p += len;
|
||||
} else
|
||||
s = NULL;
|
||||
|
||||
ret->length = (int)len;
|
||||
if (ret->data != NULL)
|
||||
OPENSSL_free(ret->data);
|
||||
ret->data = s;
|
||||
ret->type = V_ASN1_BIT_STRING;
|
||||
if (a != NULL)
|
||||
(*a) = ret;
|
||||
*pp = p;
|
||||
return (ret);
|
||||
err:
|
||||
if ((ret != NULL) && ((a == NULL) || (*a != ret)))
|
||||
M_ASN1_BIT_STRING_free(ret);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* These next 2 functions from Goetz Babin-Ebell <[email protected]>
|
||||
*/
|
||||
int ASN1_BIT_STRING_set_bit(ASN1_BIT_STRING *a, int n, int value)
|
||||
{
|
||||
int w, v, iv;
|
||||
unsigned char *c;
|
||||
|
||||
w = n / 8;
|
||||
v = 1 << (7 - (n & 0x07));
|
||||
iv = ~v;
|
||||
if (!value)
|
||||
v = 0;
|
||||
|
||||
if (a == NULL)
|
||||
return 0;
|
||||
|
||||
a->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07); /* clear, set on write */
|
||||
|
||||
if ((a->length < (w + 1)) || (a->data == NULL)) {
|
||||
if (!value)
|
||||
return (1); /* Don't need to set */
|
||||
if (a->data == NULL)
|
||||
c = (unsigned char *)OPENSSL_malloc(w + 1);
|
||||
else
|
||||
c = (unsigned char *)OPENSSL_realloc(a->data, w + 1);
|
||||
if (c == NULL) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
if (w + 1 - a->length > 0)
|
||||
OPENSSL_memset(c + a->length, 0, w + 1 - a->length);
|
||||
a->data = c;
|
||||
a->length = w + 1;
|
||||
}
|
||||
a->data[w] = ((a->data[w]) & iv) | v;
|
||||
while ((a->length > 0) && (a->data[a->length - 1] == 0))
|
||||
a->length--;
|
||||
return (1);
|
||||
}
|
||||
|
||||
int ASN1_BIT_STRING_get_bit(ASN1_BIT_STRING *a, int n)
|
||||
{
|
||||
int w, v;
|
||||
|
||||
w = n / 8;
|
||||
v = 1 << (7 - (n & 0x07));
|
||||
if ((a == NULL) || (a->length < (w + 1)) || (a->data == NULL))
|
||||
return (0);
|
||||
return ((a->data[w] & v) != 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Checks if the given bit string contains only bits specified by
|
||||
* the flags vector. Returns 0 if there is at least one bit set in 'a'
|
||||
* which is not specified in 'flags', 1 otherwise.
|
||||
* 'len' is the length of 'flags'.
|
||||
*/
|
||||
int ASN1_BIT_STRING_check(ASN1_BIT_STRING *a,
|
||||
unsigned char *flags, int flags_len)
|
||||
{
|
||||
int i, ok;
|
||||
/* Check if there is one bit set at all. */
|
||||
if (!a || !a->data)
|
||||
return 1;
|
||||
|
||||
/*
|
||||
* Check each byte of the internal representation of the bit string.
|
||||
*/
|
||||
ok = 1;
|
||||
for (i = 0; i < a->length && ok; ++i) {
|
||||
unsigned char mask = i < flags_len ? ~flags[i] : 0xff;
|
||||
/* We are done if there is an unneeded bit set. */
|
||||
ok = (a->data[i] & mask) == 0;
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
+123
@@ -0,0 +1,123 @@
|
||||
/* Copyright (C) 1995-1998 Eric Young ([email protected])
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young ([email protected]).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson ([email protected]).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young ([email protected])"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson ([email protected])"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.] */
|
||||
|
||||
#include <openssl_grpc/asn1.h>
|
||||
|
||||
#include <openssl_grpc/err.h>
|
||||
#include <openssl_grpc/mem.h>
|
||||
|
||||
int i2d_ASN1_BOOLEAN(int a, unsigned char **pp)
|
||||
{
|
||||
int r;
|
||||
unsigned char *p, *allocated = NULL;
|
||||
|
||||
r = ASN1_object_size(0, 1, V_ASN1_BOOLEAN);
|
||||
if (pp == NULL)
|
||||
return (r);
|
||||
|
||||
if (*pp == NULL) {
|
||||
if ((p = allocated = OPENSSL_malloc(r)) == NULL) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
p = *pp;
|
||||
}
|
||||
|
||||
ASN1_put_object(&p, 0, 1, V_ASN1_BOOLEAN, V_ASN1_UNIVERSAL);
|
||||
*p = (unsigned char)a;
|
||||
|
||||
/*
|
||||
* If a new buffer was allocated, just return it back.
|
||||
* If not, return the incremented buffer pointer.
|
||||
*/
|
||||
*pp = allocated != NULL ? allocated : p + 1;
|
||||
return r;
|
||||
}
|
||||
|
||||
int d2i_ASN1_BOOLEAN(int *a, const unsigned char **pp, long length)
|
||||
{
|
||||
int ret = -1;
|
||||
const unsigned char *p;
|
||||
long len;
|
||||
int inf, tag, xclass;
|
||||
int i = 0;
|
||||
|
||||
p = *pp;
|
||||
inf = ASN1_get_object(&p, &len, &tag, &xclass, length);
|
||||
if (inf & 0x80) {
|
||||
i = ASN1_R_BAD_OBJECT_HEADER;
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (tag != V_ASN1_BOOLEAN) {
|
||||
i = ASN1_R_EXPECTING_A_BOOLEAN;
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (len != 1) {
|
||||
i = ASN1_R_BOOLEAN_IS_WRONG_LENGTH;
|
||||
goto err;
|
||||
}
|
||||
ret = (int)*(p++);
|
||||
if (a != NULL)
|
||||
(*a) = ret;
|
||||
*pp = p;
|
||||
return (ret);
|
||||
err:
|
||||
OPENSSL_PUT_ERROR(ASN1, i);
|
||||
return (ret);
|
||||
}
|
||||
+123
@@ -0,0 +1,123 @@
|
||||
/* Copyright (C) 1995-1998 Eric Young ([email protected])
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young ([email protected]).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson ([email protected]).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young ([email protected])"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson ([email protected])"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.] */
|
||||
|
||||
#include <openssl/asn1.h>
|
||||
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/mem.h>
|
||||
|
||||
int i2d_ASN1_BOOLEAN(int a, unsigned char **pp)
|
||||
{
|
||||
int r;
|
||||
unsigned char *p, *allocated = NULL;
|
||||
|
||||
r = ASN1_object_size(0, 1, V_ASN1_BOOLEAN);
|
||||
if (pp == NULL)
|
||||
return (r);
|
||||
|
||||
if (*pp == NULL) {
|
||||
if ((p = allocated = OPENSSL_malloc(r)) == NULL) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
p = *pp;
|
||||
}
|
||||
|
||||
ASN1_put_object(&p, 0, 1, V_ASN1_BOOLEAN, V_ASN1_UNIVERSAL);
|
||||
*p = (unsigned char)a;
|
||||
|
||||
/*
|
||||
* If a new buffer was allocated, just return it back.
|
||||
* If not, return the incremented buffer pointer.
|
||||
*/
|
||||
*pp = allocated != NULL ? allocated : p + 1;
|
||||
return r;
|
||||
}
|
||||
|
||||
int d2i_ASN1_BOOLEAN(int *a, const unsigned char **pp, long length)
|
||||
{
|
||||
int ret = -1;
|
||||
const unsigned char *p;
|
||||
long len;
|
||||
int inf, tag, xclass;
|
||||
int i = 0;
|
||||
|
||||
p = *pp;
|
||||
inf = ASN1_get_object(&p, &len, &tag, &xclass, length);
|
||||
if (inf & 0x80) {
|
||||
i = ASN1_R_BAD_OBJECT_HEADER;
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (tag != V_ASN1_BOOLEAN) {
|
||||
i = ASN1_R_EXPECTING_A_BOOLEAN;
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (len != 1) {
|
||||
i = ASN1_R_BOOLEAN_IS_WRONG_LENGTH;
|
||||
goto err;
|
||||
}
|
||||
ret = (int)*(p++);
|
||||
if (a != NULL)
|
||||
(*a) = ret;
|
||||
*pp = p;
|
||||
return (ret);
|
||||
err:
|
||||
OPENSSL_PUT_ERROR(ASN1, i);
|
||||
return (ret);
|
||||
}
|
||||
+93
@@ -0,0 +1,93 @@
|
||||
/* Copyright (C) 1995-1998 Eric Young ([email protected])
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young ([email protected]).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson ([email protected]).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young ([email protected])"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson ([email protected])"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.] */
|
||||
|
||||
#include <openssl_grpc/asn1.h>
|
||||
|
||||
#include <limits.h>
|
||||
|
||||
#include <openssl_grpc/bio.h>
|
||||
#include <openssl_grpc/err.h>
|
||||
#include <openssl_grpc/mem.h>
|
||||
|
||||
|
||||
void *ASN1_item_d2i_bio(const ASN1_ITEM *it, BIO *in, void *x)
|
||||
{
|
||||
uint8_t *data;
|
||||
size_t len;
|
||||
// Historically, this function did not impose a limit in OpenSSL and is used
|
||||
// to read CRLs, so we leave this without an external bound.
|
||||
if (!BIO_read_asn1(in, &data, &len, INT_MAX)) {
|
||||
return NULL;
|
||||
}
|
||||
const uint8_t *ptr = data;
|
||||
void *ret = ASN1_item_d2i(x, &ptr, len, it);
|
||||
OPENSSL_free(data);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifndef OPENSSL_NO_FP_API
|
||||
void *ASN1_item_d2i_fp(const ASN1_ITEM *it, FILE *in, void *x)
|
||||
{
|
||||
BIO *b = BIO_new_fp(in, BIO_NOCLOSE);
|
||||
if (b == NULL) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_BUF_LIB);
|
||||
return NULL;
|
||||
}
|
||||
void *ret = ASN1_item_d2i_bio(it, b, x);
|
||||
BIO_free(b);
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,93 @@
|
||||
/* Copyright (C) 1995-1998 Eric Young ([email protected])
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young ([email protected]).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson ([email protected]).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young ([email protected])"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson ([email protected])"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.] */
|
||||
|
||||
#include <openssl/asn1.h>
|
||||
|
||||
#include <limits.h>
|
||||
|
||||
#include <openssl/bio.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/mem.h>
|
||||
|
||||
|
||||
void *ASN1_item_d2i_bio(const ASN1_ITEM *it, BIO *in, void *x)
|
||||
{
|
||||
uint8_t *data;
|
||||
size_t len;
|
||||
// Historically, this function did not impose a limit in OpenSSL and is used
|
||||
// to read CRLs, so we leave this without an external bound.
|
||||
if (!BIO_read_asn1(in, &data, &len, INT_MAX)) {
|
||||
return NULL;
|
||||
}
|
||||
const uint8_t *ptr = data;
|
||||
void *ret = ASN1_item_d2i(x, &ptr, len, it);
|
||||
OPENSSL_free(data);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifndef OPENSSL_NO_FP_API
|
||||
void *ASN1_item_d2i_fp(const ASN1_ITEM *it, FILE *in, void *x)
|
||||
{
|
||||
BIO *b = BIO_new_fp(in, BIO_NOCLOSE);
|
||||
if (b == NULL) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_BUF_LIB);
|
||||
return NULL;
|
||||
}
|
||||
void *ret = ASN1_item_d2i_bio(it, b, x);
|
||||
BIO_free(b);
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
+87
@@ -0,0 +1,87 @@
|
||||
/* Copyright (C) 1995-1998 Eric Young ([email protected])
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young ([email protected]).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson ([email protected]).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young ([email protected])"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson ([email protected])"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.] */
|
||||
|
||||
#include <openssl_grpc/asn1.h>
|
||||
|
||||
#include <openssl_grpc/err.h>
|
||||
#include <openssl_grpc/mem.h>
|
||||
|
||||
/*
|
||||
* 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) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
|
||||
return (NULL);
|
||||
}
|
||||
p = b;
|
||||
ret = ASN1_item_d2i(NULL, &p, i, it);
|
||||
OPENSSL_free(b);
|
||||
return (ret);
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
/* Copyright (C) 1995-1998 Eric Young ([email protected])
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young ([email protected]).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson ([email protected]).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young ([email protected])"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson ([email protected])"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.] */
|
||||
|
||||
#include <openssl/asn1.h>
|
||||
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/mem.h>
|
||||
|
||||
/*
|
||||
* 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) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
|
||||
return (NULL);
|
||||
}
|
||||
p = b;
|
||||
ret = ASN1_item_d2i(NULL, &p, i, it);
|
||||
OPENSSL_free(b);
|
||||
return (ret);
|
||||
}
|
||||
+195
@@ -0,0 +1,195 @@
|
||||
/* Copyright (C) 1995-1998 Eric Young ([email protected])
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young ([email protected]).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson ([email protected]).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young ([email protected])"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson ([email protected])"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.] */
|
||||
|
||||
#include <openssl_grpc/asn1.h>
|
||||
|
||||
#include <limits.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <openssl_grpc/err.h>
|
||||
#include <openssl_grpc/mem.h>
|
||||
|
||||
#include "../internal.h"
|
||||
|
||||
|
||||
/*
|
||||
* Code for ENUMERATED type: identical to INTEGER apart from a different tag.
|
||||
* for comments on encoding see a_int.c
|
||||
*/
|
||||
|
||||
int ASN1_ENUMERATED_set(ASN1_ENUMERATED *a, long v)
|
||||
{
|
||||
int j, k;
|
||||
unsigned int i;
|
||||
unsigned char buf[sizeof(long) + 1];
|
||||
long d;
|
||||
|
||||
a->type = V_ASN1_ENUMERATED;
|
||||
if (a->length < (int)(sizeof(long) + 1)) {
|
||||
if (a->data != NULL)
|
||||
OPENSSL_free(a->data);
|
||||
if ((a->data =
|
||||
(unsigned char *)OPENSSL_malloc(sizeof(long) + 1)) != NULL)
|
||||
OPENSSL_memset((char *)a->data, 0, sizeof(long) + 1);
|
||||
}
|
||||
if (a->data == NULL) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
|
||||
return (0);
|
||||
}
|
||||
d = v;
|
||||
if (d < 0) {
|
||||
d = -d;
|
||||
a->type = V_ASN1_NEG_ENUMERATED;
|
||||
}
|
||||
|
||||
for (i = 0; i < sizeof(long); i++) {
|
||||
if (d == 0)
|
||||
break;
|
||||
buf[i] = (int)d & 0xff;
|
||||
d >>= 8;
|
||||
}
|
||||
j = 0;
|
||||
for (k = i - 1; k >= 0; k--)
|
||||
a->data[j++] = buf[k];
|
||||
a->length = j;
|
||||
return (1);
|
||||
}
|
||||
|
||||
long ASN1_ENUMERATED_get(ASN1_ENUMERATED *a)
|
||||
{
|
||||
int neg = 0, i;
|
||||
|
||||
if (a == NULL)
|
||||
return (0L);
|
||||
i = a->type;
|
||||
if (i == V_ASN1_NEG_ENUMERATED)
|
||||
neg = 1;
|
||||
else if (i != V_ASN1_ENUMERATED)
|
||||
return -1;
|
||||
|
||||
OPENSSL_STATIC_ASSERT(sizeof(uint64_t) >= sizeof(long),
|
||||
"long larger than uint64_t");
|
||||
|
||||
if (a->length > (int)sizeof(uint64_t)) {
|
||||
/* hmm... a bit ugly */
|
||||
return -1;
|
||||
}
|
||||
|
||||
uint64_t r64 = 0;
|
||||
if (a->data != NULL) {
|
||||
for (i = 0; i < a->length; i++) {
|
||||
r64 <<= 8;
|
||||
r64 |= (unsigned char)a->data[i];
|
||||
}
|
||||
|
||||
if (r64 > LONG_MAX) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
long r = (long) r64;
|
||||
if (neg)
|
||||
r = -r;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
ASN1_ENUMERATED *BN_to_ASN1_ENUMERATED(BIGNUM *bn, ASN1_ENUMERATED *ai)
|
||||
{
|
||||
ASN1_ENUMERATED *ret;
|
||||
int len, j;
|
||||
|
||||
if (ai == NULL)
|
||||
ret = M_ASN1_ENUMERATED_new();
|
||||
else
|
||||
ret = ai;
|
||||
if (ret == NULL) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR);
|
||||
goto err;
|
||||
}
|
||||
if (BN_is_negative(bn))
|
||||
ret->type = V_ASN1_NEG_ENUMERATED;
|
||||
else
|
||||
ret->type = V_ASN1_ENUMERATED;
|
||||
j = BN_num_bits(bn);
|
||||
len = ((j == 0) ? 0 : ((j / 8) + 1));
|
||||
if (ret->length < len + 4) {
|
||||
unsigned char *new_data = OPENSSL_realloc(ret->data, len + 4);
|
||||
if (!new_data) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
ret->data = new_data;
|
||||
}
|
||||
|
||||
ret->length = BN_bn2bin(bn, ret->data);
|
||||
return (ret);
|
||||
err:
|
||||
if (ret != ai)
|
||||
M_ASN1_ENUMERATED_free(ret);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
BIGNUM *ASN1_ENUMERATED_to_BN(ASN1_ENUMERATED *ai, BIGNUM *bn)
|
||||
{
|
||||
BIGNUM *ret;
|
||||
|
||||
if ((ret = BN_bin2bn(ai->data, ai->length, bn)) == NULL)
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_BN_LIB);
|
||||
else if (ai->type == V_ASN1_NEG_ENUMERATED)
|
||||
BN_set_negative(ret, 1);
|
||||
return (ret);
|
||||
}
|
||||
+195
@@ -0,0 +1,195 @@
|
||||
/* Copyright (C) 1995-1998 Eric Young ([email protected])
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young ([email protected]).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson ([email protected]).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young ([email protected])"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson ([email protected])"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.] */
|
||||
|
||||
#include <openssl/asn1.h>
|
||||
|
||||
#include <limits.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/mem.h>
|
||||
|
||||
#include "../internal.h"
|
||||
|
||||
|
||||
/*
|
||||
* Code for ENUMERATED type: identical to INTEGER apart from a different tag.
|
||||
* for comments on encoding see a_int.c
|
||||
*/
|
||||
|
||||
int ASN1_ENUMERATED_set(ASN1_ENUMERATED *a, long v)
|
||||
{
|
||||
int j, k;
|
||||
unsigned int i;
|
||||
unsigned char buf[sizeof(long) + 1];
|
||||
long d;
|
||||
|
||||
a->type = V_ASN1_ENUMERATED;
|
||||
if (a->length < (int)(sizeof(long) + 1)) {
|
||||
if (a->data != NULL)
|
||||
OPENSSL_free(a->data);
|
||||
if ((a->data =
|
||||
(unsigned char *)OPENSSL_malloc(sizeof(long) + 1)) != NULL)
|
||||
OPENSSL_memset((char *)a->data, 0, sizeof(long) + 1);
|
||||
}
|
||||
if (a->data == NULL) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
|
||||
return (0);
|
||||
}
|
||||
d = v;
|
||||
if (d < 0) {
|
||||
d = -d;
|
||||
a->type = V_ASN1_NEG_ENUMERATED;
|
||||
}
|
||||
|
||||
for (i = 0; i < sizeof(long); i++) {
|
||||
if (d == 0)
|
||||
break;
|
||||
buf[i] = (int)d & 0xff;
|
||||
d >>= 8;
|
||||
}
|
||||
j = 0;
|
||||
for (k = i - 1; k >= 0; k--)
|
||||
a->data[j++] = buf[k];
|
||||
a->length = j;
|
||||
return (1);
|
||||
}
|
||||
|
||||
long ASN1_ENUMERATED_get(ASN1_ENUMERATED *a)
|
||||
{
|
||||
int neg = 0, i;
|
||||
|
||||
if (a == NULL)
|
||||
return (0L);
|
||||
i = a->type;
|
||||
if (i == V_ASN1_NEG_ENUMERATED)
|
||||
neg = 1;
|
||||
else if (i != V_ASN1_ENUMERATED)
|
||||
return -1;
|
||||
|
||||
OPENSSL_STATIC_ASSERT(sizeof(uint64_t) >= sizeof(long),
|
||||
"long larger than uint64_t");
|
||||
|
||||
if (a->length > (int)sizeof(uint64_t)) {
|
||||
/* hmm... a bit ugly */
|
||||
return -1;
|
||||
}
|
||||
|
||||
uint64_t r64 = 0;
|
||||
if (a->data != NULL) {
|
||||
for (i = 0; i < a->length; i++) {
|
||||
r64 <<= 8;
|
||||
r64 |= (unsigned char)a->data[i];
|
||||
}
|
||||
|
||||
if (r64 > LONG_MAX) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
long r = (long) r64;
|
||||
if (neg)
|
||||
r = -r;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
ASN1_ENUMERATED *BN_to_ASN1_ENUMERATED(BIGNUM *bn, ASN1_ENUMERATED *ai)
|
||||
{
|
||||
ASN1_ENUMERATED *ret;
|
||||
int len, j;
|
||||
|
||||
if (ai == NULL)
|
||||
ret = M_ASN1_ENUMERATED_new();
|
||||
else
|
||||
ret = ai;
|
||||
if (ret == NULL) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR);
|
||||
goto err;
|
||||
}
|
||||
if (BN_is_negative(bn))
|
||||
ret->type = V_ASN1_NEG_ENUMERATED;
|
||||
else
|
||||
ret->type = V_ASN1_ENUMERATED;
|
||||
j = BN_num_bits(bn);
|
||||
len = ((j == 0) ? 0 : ((j / 8) + 1));
|
||||
if (ret->length < len + 4) {
|
||||
unsigned char *new_data = OPENSSL_realloc(ret->data, len + 4);
|
||||
if (!new_data) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
ret->data = new_data;
|
||||
}
|
||||
|
||||
ret->length = BN_bn2bin(bn, ret->data);
|
||||
return (ret);
|
||||
err:
|
||||
if (ret != ai)
|
||||
M_ASN1_ENUMERATED_free(ret);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
BIGNUM *ASN1_ENUMERATED_to_BN(ASN1_ENUMERATED *ai, BIGNUM *bn)
|
||||
{
|
||||
BIGNUM *ret;
|
||||
|
||||
if ((ret = BN_bin2bn(ai->data, ai->length, bn)) == NULL)
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_BN_LIB);
|
||||
else if (ai->type == V_ASN1_NEG_ENUMERATED)
|
||||
BN_set_negative(ret, 1);
|
||||
return (ret);
|
||||
}
|
||||
+261
@@ -0,0 +1,261 @@
|
||||
/* Copyright (C) 1995-1998 Eric Young ([email protected])
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young ([email protected]).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson ([email protected]).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young ([email protected])"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson ([email protected])"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.] */
|
||||
|
||||
#include <openssl_grpc/asn1.h>
|
||||
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
#include <openssl_grpc/err.h>
|
||||
#include <openssl_grpc/mem.h>
|
||||
|
||||
#include "asn1_locl.h"
|
||||
|
||||
int asn1_generalizedtime_to_tm(struct tm *tm, const ASN1_GENERALIZEDTIME *d)
|
||||
{
|
||||
static const int min[9] = { 0, 0, 1, 1, 0, 0, 0, 0, 0 };
|
||||
static const int max[9] = { 99, 99, 12, 31, 23, 59, 59, 12, 59 };
|
||||
char *a;
|
||||
int n, i, l, o;
|
||||
|
||||
if (d->type != V_ASN1_GENERALIZEDTIME)
|
||||
return (0);
|
||||
l = d->length;
|
||||
a = (char *)d->data;
|
||||
o = 0;
|
||||
/*
|
||||
* GENERALIZEDTIME is similar to UTCTIME except the year is represented
|
||||
* as YYYY. This stuff treats everything as a two digit field so make
|
||||
* first two fields 00 to 99
|
||||
*/
|
||||
if (l < 13)
|
||||
goto err;
|
||||
for (i = 0; i < 7; i++) {
|
||||
if ((i == 6) && ((a[o] == 'Z') || (a[o] == '+') || (a[o] == '-'))) {
|
||||
i++;
|
||||
if (tm)
|
||||
tm->tm_sec = 0;
|
||||
break;
|
||||
}
|
||||
if ((a[o] < '0') || (a[o] > '9'))
|
||||
goto err;
|
||||
n = a[o] - '0';
|
||||
if (++o > l)
|
||||
goto err;
|
||||
|
||||
if ((a[o] < '0') || (a[o] > '9'))
|
||||
goto err;
|
||||
n = (n * 10) + a[o] - '0';
|
||||
if (++o > l)
|
||||
goto err;
|
||||
|
||||
if ((n < min[i]) || (n > max[i]))
|
||||
goto err;
|
||||
if (tm) {
|
||||
switch (i) {
|
||||
case 0:
|
||||
tm->tm_year = n * 100 - 1900;
|
||||
break;
|
||||
case 1:
|
||||
tm->tm_year += n;
|
||||
break;
|
||||
case 2:
|
||||
tm->tm_mon = n - 1;
|
||||
break;
|
||||
case 3:
|
||||
tm->tm_mday = n;
|
||||
break;
|
||||
case 4:
|
||||
tm->tm_hour = n;
|
||||
break;
|
||||
case 5:
|
||||
tm->tm_min = n;
|
||||
break;
|
||||
case 6:
|
||||
tm->tm_sec = n;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Optional fractional seconds: decimal point followed by one or more
|
||||
* digits.
|
||||
*/
|
||||
if (a[o] == '.') {
|
||||
if (++o > l)
|
||||
goto err;
|
||||
i = o;
|
||||
while ((a[o] >= '0') && (a[o] <= '9') && (o <= l))
|
||||
o++;
|
||||
/* Must have at least one digit after decimal point */
|
||||
if (i == o)
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (a[o] == 'Z')
|
||||
o++;
|
||||
else if ((a[o] == '+') || (a[o] == '-')) {
|
||||
int offsign = a[o] == '-' ? 1 : -1, offset = 0;
|
||||
o++;
|
||||
if (o + 4 > l)
|
||||
goto err;
|
||||
for (i = 7; i < 9; i++) {
|
||||
if ((a[o] < '0') || (a[o] > '9'))
|
||||
goto err;
|
||||
n = a[o] - '0';
|
||||
o++;
|
||||
if ((a[o] < '0') || (a[o] > '9'))
|
||||
goto err;
|
||||
n = (n * 10) + a[o] - '0';
|
||||
if ((n < min[i]) || (n > max[i]))
|
||||
goto err;
|
||||
if (tm) {
|
||||
if (i == 7)
|
||||
offset = n * 3600;
|
||||
else if (i == 8)
|
||||
offset += n * 60;
|
||||
}
|
||||
o++;
|
||||
}
|
||||
if (offset && !OPENSSL_gmtime_adj(tm, 0, offset * offsign))
|
||||
return 0;
|
||||
} else if (a[o]) {
|
||||
/* Missing time zone information. */
|
||||
goto err;
|
||||
}
|
||||
return (o == l);
|
||||
err:
|
||||
return (0);
|
||||
}
|
||||
|
||||
int ASN1_GENERALIZEDTIME_check(const ASN1_GENERALIZEDTIME *d)
|
||||
{
|
||||
return asn1_generalizedtime_to_tm(NULL, d);
|
||||
}
|
||||
|
||||
int ASN1_GENERALIZEDTIME_set_string(ASN1_GENERALIZEDTIME *s, const char *str)
|
||||
{
|
||||
ASN1_GENERALIZEDTIME t;
|
||||
|
||||
t.type = V_ASN1_GENERALIZEDTIME;
|
||||
t.length = strlen(str);
|
||||
t.data = (unsigned char *)str;
|
||||
if (ASN1_GENERALIZEDTIME_check(&t)) {
|
||||
if (s != NULL) {
|
||||
if (!ASN1_STRING_set((ASN1_STRING *)s,
|
||||
(unsigned char *)str, t.length))
|
||||
return 0;
|
||||
s->type = V_ASN1_GENERALIZEDTIME;
|
||||
}
|
||||
return (1);
|
||||
} else
|
||||
return (0);
|
||||
}
|
||||
|
||||
ASN1_GENERALIZEDTIME *ASN1_GENERALIZEDTIME_set(ASN1_GENERALIZEDTIME *s,
|
||||
time_t t)
|
||||
{
|
||||
return ASN1_GENERALIZEDTIME_adj(s, t, 0, 0);
|
||||
}
|
||||
|
||||
ASN1_GENERALIZEDTIME *ASN1_GENERALIZEDTIME_adj(ASN1_GENERALIZEDTIME *s,
|
||||
time_t t, int offset_day,
|
||||
long offset_sec)
|
||||
{
|
||||
char *p;
|
||||
struct tm *ts;
|
||||
struct tm data;
|
||||
size_t len = 20;
|
||||
ASN1_GENERALIZEDTIME *tmps = NULL;
|
||||
|
||||
if (s == NULL)
|
||||
tmps = ASN1_GENERALIZEDTIME_new();
|
||||
else
|
||||
tmps = s;
|
||||
if (tmps == NULL)
|
||||
return NULL;
|
||||
|
||||
ts = OPENSSL_gmtime(&t, &data);
|
||||
if (ts == NULL)
|
||||
goto err;
|
||||
|
||||
if (offset_day || offset_sec) {
|
||||
if (!OPENSSL_gmtime_adj(ts, offset_day, offset_sec))
|
||||
goto err;
|
||||
}
|
||||
|
||||
p = (char *)tmps->data;
|
||||
if ((p == NULL) || ((size_t)tmps->length < len)) {
|
||||
p = OPENSSL_malloc(len);
|
||||
if (p == NULL) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
OPENSSL_free(tmps->data);
|
||||
tmps->data = (unsigned char *)p;
|
||||
}
|
||||
|
||||
BIO_snprintf(p, len, "%04d%02d%02d%02d%02d%02dZ", ts->tm_year + 1900,
|
||||
ts->tm_mon + 1, ts->tm_mday, ts->tm_hour, ts->tm_min,
|
||||
ts->tm_sec);
|
||||
tmps->length = strlen(p);
|
||||
tmps->type = V_ASN1_GENERALIZEDTIME;
|
||||
return tmps;
|
||||
err:
|
||||
if (s == NULL)
|
||||
ASN1_GENERALIZEDTIME_free(tmps);
|
||||
return NULL;
|
||||
}
|
||||
+261
@@ -0,0 +1,261 @@
|
||||
/* Copyright (C) 1995-1998 Eric Young ([email protected])
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young ([email protected]).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson ([email protected]).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young ([email protected])"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson ([email protected])"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.] */
|
||||
|
||||
#include <openssl/asn1.h>
|
||||
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/mem.h>
|
||||
|
||||
#include "asn1_locl.h"
|
||||
|
||||
int asn1_generalizedtime_to_tm(struct tm *tm, const ASN1_GENERALIZEDTIME *d)
|
||||
{
|
||||
static const int min[9] = { 0, 0, 1, 1, 0, 0, 0, 0, 0 };
|
||||
static const int max[9] = { 99, 99, 12, 31, 23, 59, 59, 12, 59 };
|
||||
char *a;
|
||||
int n, i, l, o;
|
||||
|
||||
if (d->type != V_ASN1_GENERALIZEDTIME)
|
||||
return (0);
|
||||
l = d->length;
|
||||
a = (char *)d->data;
|
||||
o = 0;
|
||||
/*
|
||||
* GENERALIZEDTIME is similar to UTCTIME except the year is represented
|
||||
* as YYYY. This stuff treats everything as a two digit field so make
|
||||
* first two fields 00 to 99
|
||||
*/
|
||||
if (l < 13)
|
||||
goto err;
|
||||
for (i = 0; i < 7; i++) {
|
||||
if ((i == 6) && ((a[o] == 'Z') || (a[o] == '+') || (a[o] == '-'))) {
|
||||
i++;
|
||||
if (tm)
|
||||
tm->tm_sec = 0;
|
||||
break;
|
||||
}
|
||||
if ((a[o] < '0') || (a[o] > '9'))
|
||||
goto err;
|
||||
n = a[o] - '0';
|
||||
if (++o > l)
|
||||
goto err;
|
||||
|
||||
if ((a[o] < '0') || (a[o] > '9'))
|
||||
goto err;
|
||||
n = (n * 10) + a[o] - '0';
|
||||
if (++o > l)
|
||||
goto err;
|
||||
|
||||
if ((n < min[i]) || (n > max[i]))
|
||||
goto err;
|
||||
if (tm) {
|
||||
switch (i) {
|
||||
case 0:
|
||||
tm->tm_year = n * 100 - 1900;
|
||||
break;
|
||||
case 1:
|
||||
tm->tm_year += n;
|
||||
break;
|
||||
case 2:
|
||||
tm->tm_mon = n - 1;
|
||||
break;
|
||||
case 3:
|
||||
tm->tm_mday = n;
|
||||
break;
|
||||
case 4:
|
||||
tm->tm_hour = n;
|
||||
break;
|
||||
case 5:
|
||||
tm->tm_min = n;
|
||||
break;
|
||||
case 6:
|
||||
tm->tm_sec = n;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Optional fractional seconds: decimal point followed by one or more
|
||||
* digits.
|
||||
*/
|
||||
if (a[o] == '.') {
|
||||
if (++o > l)
|
||||
goto err;
|
||||
i = o;
|
||||
while ((a[o] >= '0') && (a[o] <= '9') && (o <= l))
|
||||
o++;
|
||||
/* Must have at least one digit after decimal point */
|
||||
if (i == o)
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (a[o] == 'Z')
|
||||
o++;
|
||||
else if ((a[o] == '+') || (a[o] == '-')) {
|
||||
int offsign = a[o] == '-' ? 1 : -1, offset = 0;
|
||||
o++;
|
||||
if (o + 4 > l)
|
||||
goto err;
|
||||
for (i = 7; i < 9; i++) {
|
||||
if ((a[o] < '0') || (a[o] > '9'))
|
||||
goto err;
|
||||
n = a[o] - '0';
|
||||
o++;
|
||||
if ((a[o] < '0') || (a[o] > '9'))
|
||||
goto err;
|
||||
n = (n * 10) + a[o] - '0';
|
||||
if ((n < min[i]) || (n > max[i]))
|
||||
goto err;
|
||||
if (tm) {
|
||||
if (i == 7)
|
||||
offset = n * 3600;
|
||||
else if (i == 8)
|
||||
offset += n * 60;
|
||||
}
|
||||
o++;
|
||||
}
|
||||
if (offset && !OPENSSL_gmtime_adj(tm, 0, offset * offsign))
|
||||
return 0;
|
||||
} else if (a[o]) {
|
||||
/* Missing time zone information. */
|
||||
goto err;
|
||||
}
|
||||
return (o == l);
|
||||
err:
|
||||
return (0);
|
||||
}
|
||||
|
||||
int ASN1_GENERALIZEDTIME_check(const ASN1_GENERALIZEDTIME *d)
|
||||
{
|
||||
return asn1_generalizedtime_to_tm(NULL, d);
|
||||
}
|
||||
|
||||
int ASN1_GENERALIZEDTIME_set_string(ASN1_GENERALIZEDTIME *s, const char *str)
|
||||
{
|
||||
ASN1_GENERALIZEDTIME t;
|
||||
|
||||
t.type = V_ASN1_GENERALIZEDTIME;
|
||||
t.length = strlen(str);
|
||||
t.data = (unsigned char *)str;
|
||||
if (ASN1_GENERALIZEDTIME_check(&t)) {
|
||||
if (s != NULL) {
|
||||
if (!ASN1_STRING_set((ASN1_STRING *)s,
|
||||
(unsigned char *)str, t.length))
|
||||
return 0;
|
||||
s->type = V_ASN1_GENERALIZEDTIME;
|
||||
}
|
||||
return (1);
|
||||
} else
|
||||
return (0);
|
||||
}
|
||||
|
||||
ASN1_GENERALIZEDTIME *ASN1_GENERALIZEDTIME_set(ASN1_GENERALIZEDTIME *s,
|
||||
time_t t)
|
||||
{
|
||||
return ASN1_GENERALIZEDTIME_adj(s, t, 0, 0);
|
||||
}
|
||||
|
||||
ASN1_GENERALIZEDTIME *ASN1_GENERALIZEDTIME_adj(ASN1_GENERALIZEDTIME *s,
|
||||
time_t t, int offset_day,
|
||||
long offset_sec)
|
||||
{
|
||||
char *p;
|
||||
struct tm *ts;
|
||||
struct tm data;
|
||||
size_t len = 20;
|
||||
ASN1_GENERALIZEDTIME *tmps = NULL;
|
||||
|
||||
if (s == NULL)
|
||||
tmps = ASN1_GENERALIZEDTIME_new();
|
||||
else
|
||||
tmps = s;
|
||||
if (tmps == NULL)
|
||||
return NULL;
|
||||
|
||||
ts = OPENSSL_gmtime(&t, &data);
|
||||
if (ts == NULL)
|
||||
goto err;
|
||||
|
||||
if (offset_day || offset_sec) {
|
||||
if (!OPENSSL_gmtime_adj(ts, offset_day, offset_sec))
|
||||
goto err;
|
||||
}
|
||||
|
||||
p = (char *)tmps->data;
|
||||
if ((p == NULL) || ((size_t)tmps->length < len)) {
|
||||
p = OPENSSL_malloc(len);
|
||||
if (p == NULL) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
OPENSSL_free(tmps->data);
|
||||
tmps->data = (unsigned char *)p;
|
||||
}
|
||||
|
||||
BIO_snprintf(p, len, "%04d%02d%02d%02d%02d%02dZ", ts->tm_year + 1900,
|
||||
ts->tm_mon + 1, ts->tm_mday, ts->tm_hour, ts->tm_min,
|
||||
ts->tm_sec);
|
||||
tmps->length = strlen(p);
|
||||
tmps->type = V_ASN1_GENERALIZEDTIME;
|
||||
return tmps;
|
||||
err:
|
||||
if (s == NULL)
|
||||
ASN1_GENERALIZEDTIME_free(tmps);
|
||||
return NULL;
|
||||
}
|
||||
+88
@@ -0,0 +1,88 @@
|
||||
/* Copyright (C) 1995-1998 Eric Young ([email protected])
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young ([email protected]).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson ([email protected]).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young ([email protected])"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson ([email protected])"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.] */
|
||||
|
||||
#include <openssl_grpc/asn1.h>
|
||||
|
||||
#include <openssl_grpc/bio.h>
|
||||
#include <openssl_grpc/err.h>
|
||||
#include <openssl_grpc/mem.h>
|
||||
|
||||
|
||||
int ASN1_item_i2d_fp(const ASN1_ITEM *it, FILE *out, void *x)
|
||||
{
|
||||
BIO *b = BIO_new_fp(out, BIO_NOCLOSE);
|
||||
if (b == NULL) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_BUF_LIB);
|
||||
return 0;
|
||||
}
|
||||
int ret = ASN1_item_i2d_bio(it, b, x);
|
||||
BIO_free(b);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ASN1_item_i2d_bio(const ASN1_ITEM *it, BIO *out, void *x)
|
||||
{
|
||||
unsigned char *b = NULL;
|
||||
int n = ASN1_item_i2d(x, &b, it);
|
||||
if (b == NULL) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ret = BIO_write_all(out, b, n);
|
||||
OPENSSL_free(b);
|
||||
return ret;
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
/* Copyright (C) 1995-1998 Eric Young ([email protected])
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young ([email protected]).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson ([email protected]).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young ([email protected])"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson ([email protected])"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.] */
|
||||
|
||||
#include <openssl/asn1.h>
|
||||
|
||||
#include <openssl/bio.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/mem.h>
|
||||
|
||||
|
||||
int ASN1_item_i2d_fp(const ASN1_ITEM *it, FILE *out, void *x)
|
||||
{
|
||||
BIO *b = BIO_new_fp(out, BIO_NOCLOSE);
|
||||
if (b == NULL) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_BUF_LIB);
|
||||
return 0;
|
||||
}
|
||||
int ret = ASN1_item_i2d_bio(it, b, x);
|
||||
BIO_free(b);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ASN1_item_i2d_bio(const ASN1_ITEM *it, BIO *out, void *x)
|
||||
{
|
||||
unsigned char *b = NULL;
|
||||
int n = ASN1_item_i2d(x, &b, it);
|
||||
if (b == NULL) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ret = BIO_write_all(out, b, n);
|
||||
OPENSSL_free(b);
|
||||
return ret;
|
||||
}
|
||||
+420
@@ -0,0 +1,420 @@
|
||||
/* Copyright (C) 1995-1998 Eric Young ([email protected])
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young ([email protected]).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson ([email protected]).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young ([email protected])"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson ([email protected])"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.] */
|
||||
|
||||
#include <openssl_grpc/asn1.h>
|
||||
|
||||
#include <string.h>
|
||||
#include <limits.h>
|
||||
|
||||
#include <openssl_grpc/err.h>
|
||||
#include <openssl_grpc/mem.h>
|
||||
|
||||
#include "../internal.h"
|
||||
|
||||
|
||||
ASN1_INTEGER *ASN1_INTEGER_dup(const ASN1_INTEGER *x)
|
||||
{
|
||||
return M_ASN1_INTEGER_dup(x);
|
||||
}
|
||||
|
||||
int ASN1_INTEGER_cmp(const ASN1_INTEGER *x, const ASN1_INTEGER *y)
|
||||
{
|
||||
int neg, ret;
|
||||
/* Compare signs */
|
||||
neg = x->type & V_ASN1_NEG;
|
||||
if (neg != (y->type & V_ASN1_NEG)) {
|
||||
if (neg)
|
||||
return -1;
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
|
||||
ret = ASN1_STRING_cmp(x, y);
|
||||
|
||||
if (neg)
|
||||
return -ret;
|
||||
else
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* This converts an ASN1 INTEGER into its content encoding.
|
||||
* The internal representation is an ASN1_STRING whose data is a big endian
|
||||
* representation of the value, ignoring the sign. The sign is determined by
|
||||
* the type: V_ASN1_INTEGER for positive and V_ASN1_NEG_INTEGER for negative.
|
||||
*
|
||||
* Positive integers are no problem: they are almost the same as the DER
|
||||
* encoding, except if the first byte is >= 0x80 we need to add a zero pad.
|
||||
*
|
||||
* Negative integers are a bit trickier...
|
||||
* The DER representation of negative integers is in 2s complement form.
|
||||
* The internal form is converted by complementing each octet and finally
|
||||
* adding one to the result. This can be done less messily with a little trick.
|
||||
* If the internal form has trailing zeroes then they will become FF by the
|
||||
* complement and 0 by the add one (due to carry) so just copy as many trailing
|
||||
* zeros to the destination as there are in the source. The carry will add one
|
||||
* to the last none zero octet: so complement this octet and add one and finally
|
||||
* complement any left over until you get to the start of the string.
|
||||
*
|
||||
* Padding is a little trickier too. If the first bytes is > 0x80 then we pad
|
||||
* with 0xff. However if the first byte is 0x80 and one of the following bytes
|
||||
* is non-zero we pad with 0xff. The reason for this distinction is that 0x80
|
||||
* followed by optional zeros isn't padded.
|
||||
*/
|
||||
|
||||
int i2c_ASN1_INTEGER(ASN1_INTEGER *a, unsigned char **pp)
|
||||
{
|
||||
int pad = 0, ret, i, neg;
|
||||
unsigned char *p, *n, pb = 0;
|
||||
|
||||
if (a == NULL)
|
||||
return (0);
|
||||
neg = a->type & V_ASN1_NEG;
|
||||
if (a->length == 0)
|
||||
ret = 1;
|
||||
else {
|
||||
ret = a->length;
|
||||
i = a->data[0];
|
||||
if (ret == 1 && i == 0)
|
||||
neg = 0;
|
||||
if (!neg && (i > 127)) {
|
||||
pad = 1;
|
||||
pb = 0;
|
||||
} else if (neg) {
|
||||
if (i > 128) {
|
||||
pad = 1;
|
||||
pb = 0xFF;
|
||||
} else if (i == 128) {
|
||||
/*
|
||||
* Special case: if any other bytes non zero we pad:
|
||||
* otherwise we don't.
|
||||
*/
|
||||
for (i = 1; i < a->length; i++)
|
||||
if (a->data[i]) {
|
||||
pad = 1;
|
||||
pb = 0xFF;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
ret += pad;
|
||||
}
|
||||
if (pp == NULL)
|
||||
return (ret);
|
||||
p = *pp;
|
||||
|
||||
if (pad)
|
||||
*(p++) = pb;
|
||||
if (a->length == 0)
|
||||
*(p++) = 0;
|
||||
else if (!neg)
|
||||
OPENSSL_memcpy(p, a->data, (unsigned int)a->length);
|
||||
else {
|
||||
/* Begin at the end of the encoding */
|
||||
n = a->data + a->length - 1;
|
||||
p += a->length - 1;
|
||||
i = a->length;
|
||||
/* Copy zeros to destination as long as source is zero */
|
||||
while (!*n && i > 1) {
|
||||
*(p--) = 0;
|
||||
n--;
|
||||
i--;
|
||||
}
|
||||
/* Complement and increment next octet */
|
||||
*(p--) = ((*(n--)) ^ 0xff) + 1;
|
||||
i--;
|
||||
/* Complement any octets left */
|
||||
for (; i > 0; i--)
|
||||
*(p--) = *(n--) ^ 0xff;
|
||||
}
|
||||
|
||||
*pp += ret;
|
||||
return (ret);
|
||||
}
|
||||
|
||||
/* Convert just ASN1 INTEGER content octets to ASN1_INTEGER structure */
|
||||
|
||||
ASN1_INTEGER *c2i_ASN1_INTEGER(ASN1_INTEGER **a, const unsigned char **pp,
|
||||
long len)
|
||||
{
|
||||
ASN1_INTEGER *ret = NULL;
|
||||
const unsigned char *p, *pend;
|
||||
unsigned char *to, *s;
|
||||
int i;
|
||||
|
||||
/*
|
||||
* This function can handle lengths up to INT_MAX - 1, but the rest of the
|
||||
* legacy ASN.1 code mixes integer types, so avoid exposing it to
|
||||
* ASN1_INTEGERS with larger lengths.
|
||||
*/
|
||||
if (len < 0 || len > INT_MAX / 2) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_TOO_LONG);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ((a == NULL) || ((*a) == NULL)) {
|
||||
if ((ret = M_ASN1_INTEGER_new()) == NULL)
|
||||
return (NULL);
|
||||
ret->type = V_ASN1_INTEGER;
|
||||
} else
|
||||
ret = (*a);
|
||||
|
||||
p = *pp;
|
||||
pend = p + len;
|
||||
|
||||
/*
|
||||
* We must OPENSSL_malloc stuff, even for 0 bytes otherwise it signifies
|
||||
* a missing NULL parameter.
|
||||
*/
|
||||
s = (unsigned char *)OPENSSL_malloc((int)len + 1);
|
||||
if (s == NULL) {
|
||||
i = ERR_R_MALLOC_FAILURE;
|
||||
goto err;
|
||||
}
|
||||
to = s;
|
||||
if (!len) {
|
||||
/*
|
||||
* Strictly speaking this is an illegal INTEGER but we tolerate it.
|
||||
*/
|
||||
ret->type = V_ASN1_INTEGER;
|
||||
} else if (*p & 0x80) { /* a negative number */
|
||||
ret->type = V_ASN1_NEG_INTEGER;
|
||||
if ((*p == 0xff) && (len != 1)) {
|
||||
p++;
|
||||
len--;
|
||||
}
|
||||
i = len;
|
||||
p += i - 1;
|
||||
to += i - 1;
|
||||
while ((!*p) && i) {
|
||||
*(to--) = 0;
|
||||
i--;
|
||||
p--;
|
||||
}
|
||||
/*
|
||||
* Special case: if all zeros then the number will be of the form FF
|
||||
* followed by n zero bytes: this corresponds to 1 followed by n zero
|
||||
* bytes. We've already written n zeros so we just append an extra
|
||||
* one and set the first byte to a 1. This is treated separately
|
||||
* because it is the only case where the number of bytes is larger
|
||||
* than len.
|
||||
*/
|
||||
if (!i) {
|
||||
*s = 1;
|
||||
s[len] = 0;
|
||||
len++;
|
||||
} else {
|
||||
*(to--) = (*(p--) ^ 0xff) + 1;
|
||||
i--;
|
||||
for (; i > 0; i--)
|
||||
*(to--) = *(p--) ^ 0xff;
|
||||
}
|
||||
} else {
|
||||
ret->type = V_ASN1_INTEGER;
|
||||
if ((*p == 0) && (len != 1)) {
|
||||
p++;
|
||||
len--;
|
||||
}
|
||||
OPENSSL_memcpy(s, p, (int)len);
|
||||
}
|
||||
|
||||
if (ret->data != NULL)
|
||||
OPENSSL_free(ret->data);
|
||||
ret->data = s;
|
||||
ret->length = (int)len;
|
||||
if (a != NULL)
|
||||
(*a) = ret;
|
||||
*pp = pend;
|
||||
return (ret);
|
||||
err:
|
||||
OPENSSL_PUT_ERROR(ASN1, i);
|
||||
if ((ret != NULL) && ((a == NULL) || (*a != ret)))
|
||||
M_ASN1_INTEGER_free(ret);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
int ASN1_INTEGER_set(ASN1_INTEGER *a, long v)
|
||||
{
|
||||
if (v >= 0) {
|
||||
return ASN1_INTEGER_set_uint64(a, (uint64_t) v);
|
||||
}
|
||||
|
||||
if (!ASN1_INTEGER_set_uint64(a, 0 - (uint64_t) v)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
a->type = V_ASN1_NEG_INTEGER;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ASN1_INTEGER_set_uint64(ASN1_INTEGER *out, uint64_t v)
|
||||
{
|
||||
uint8_t *const newdata = OPENSSL_malloc(sizeof(uint64_t));
|
||||
if (newdata == NULL) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
OPENSSL_free(out->data);
|
||||
out->data = newdata;
|
||||
v = CRYPTO_bswap8(v);
|
||||
memcpy(out->data, &v, sizeof(v));
|
||||
|
||||
out->type = V_ASN1_INTEGER;
|
||||
|
||||
size_t leading_zeros;
|
||||
for (leading_zeros = 0; leading_zeros < sizeof(uint64_t) - 1;
|
||||
leading_zeros++) {
|
||||
if (out->data[leading_zeros] != 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
out->length = sizeof(uint64_t) - leading_zeros;
|
||||
OPENSSL_memmove(out->data, out->data + leading_zeros, out->length);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
long ASN1_INTEGER_get(const ASN1_INTEGER *a)
|
||||
{
|
||||
int neg = 0, i;
|
||||
|
||||
if (a == NULL)
|
||||
return (0L);
|
||||
i = a->type;
|
||||
if (i == V_ASN1_NEG_INTEGER)
|
||||
neg = 1;
|
||||
else if (i != V_ASN1_INTEGER)
|
||||
return -1;
|
||||
|
||||
OPENSSL_STATIC_ASSERT(sizeof(uint64_t) >= sizeof(long),
|
||||
"long larger than uint64_t");
|
||||
|
||||
if (a->length > (int)sizeof(uint64_t)) {
|
||||
/* hmm... a bit ugly, return all ones */
|
||||
return -1;
|
||||
}
|
||||
|
||||
uint64_t r64 = 0;
|
||||
if (a->data != NULL) {
|
||||
for (i = 0; i < a->length; i++) {
|
||||
r64 <<= 8;
|
||||
r64 |= (unsigned char)a->data[i];
|
||||
}
|
||||
|
||||
if (r64 > LONG_MAX) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
long r = (long) r64;
|
||||
if (neg)
|
||||
r = -r;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
ASN1_INTEGER *BN_to_ASN1_INTEGER(const BIGNUM *bn, ASN1_INTEGER *ai)
|
||||
{
|
||||
ASN1_INTEGER *ret;
|
||||
int len, j;
|
||||
|
||||
if (ai == NULL)
|
||||
ret = M_ASN1_INTEGER_new();
|
||||
else
|
||||
ret = ai;
|
||||
if (ret == NULL) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR);
|
||||
goto err;
|
||||
}
|
||||
if (BN_is_negative(bn) && !BN_is_zero(bn))
|
||||
ret->type = V_ASN1_NEG_INTEGER;
|
||||
else
|
||||
ret->type = V_ASN1_INTEGER;
|
||||
j = BN_num_bits(bn);
|
||||
len = ((j == 0) ? 0 : ((j / 8) + 1));
|
||||
if (ret->length < len + 4) {
|
||||
unsigned char *new_data = OPENSSL_realloc(ret->data, len + 4);
|
||||
if (!new_data) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
ret->data = new_data;
|
||||
}
|
||||
ret->length = BN_bn2bin(bn, ret->data);
|
||||
/* Correct zero case */
|
||||
if (!ret->length) {
|
||||
ret->data[0] = 0;
|
||||
ret->length = 1;
|
||||
}
|
||||
return (ret);
|
||||
err:
|
||||
if (ret != ai)
|
||||
M_ASN1_INTEGER_free(ret);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
BIGNUM *ASN1_INTEGER_to_BN(const ASN1_INTEGER *ai, BIGNUM *bn)
|
||||
{
|
||||
BIGNUM *ret;
|
||||
|
||||
if ((ret = BN_bin2bn(ai->data, ai->length, bn)) == NULL)
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_BN_LIB);
|
||||
else if (ai->type == V_ASN1_NEG_INTEGER)
|
||||
BN_set_negative(ret, 1);
|
||||
return (ret);
|
||||
}
|
||||
+420
@@ -0,0 +1,420 @@
|
||||
/* Copyright (C) 1995-1998 Eric Young ([email protected])
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young ([email protected]).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson ([email protected]).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young ([email protected])"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson ([email protected])"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.] */
|
||||
|
||||
#include <openssl/asn1.h>
|
||||
|
||||
#include <string.h>
|
||||
#include <limits.h>
|
||||
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/mem.h>
|
||||
|
||||
#include "../internal.h"
|
||||
|
||||
|
||||
ASN1_INTEGER *ASN1_INTEGER_dup(const ASN1_INTEGER *x)
|
||||
{
|
||||
return M_ASN1_INTEGER_dup(x);
|
||||
}
|
||||
|
||||
int ASN1_INTEGER_cmp(const ASN1_INTEGER *x, const ASN1_INTEGER *y)
|
||||
{
|
||||
int neg, ret;
|
||||
/* Compare signs */
|
||||
neg = x->type & V_ASN1_NEG;
|
||||
if (neg != (y->type & V_ASN1_NEG)) {
|
||||
if (neg)
|
||||
return -1;
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
|
||||
ret = ASN1_STRING_cmp(x, y);
|
||||
|
||||
if (neg)
|
||||
return -ret;
|
||||
else
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* This converts an ASN1 INTEGER into its content encoding.
|
||||
* The internal representation is an ASN1_STRING whose data is a big endian
|
||||
* representation of the value, ignoring the sign. The sign is determined by
|
||||
* the type: V_ASN1_INTEGER for positive and V_ASN1_NEG_INTEGER for negative.
|
||||
*
|
||||
* Positive integers are no problem: they are almost the same as the DER
|
||||
* encoding, except if the first byte is >= 0x80 we need to add a zero pad.
|
||||
*
|
||||
* Negative integers are a bit trickier...
|
||||
* The DER representation of negative integers is in 2s complement form.
|
||||
* The internal form is converted by complementing each octet and finally
|
||||
* adding one to the result. This can be done less messily with a little trick.
|
||||
* If the internal form has trailing zeroes then they will become FF by the
|
||||
* complement and 0 by the add one (due to carry) so just copy as many trailing
|
||||
* zeros to the destination as there are in the source. The carry will add one
|
||||
* to the last none zero octet: so complement this octet and add one and finally
|
||||
* complement any left over until you get to the start of the string.
|
||||
*
|
||||
* Padding is a little trickier too. If the first bytes is > 0x80 then we pad
|
||||
* with 0xff. However if the first byte is 0x80 and one of the following bytes
|
||||
* is non-zero we pad with 0xff. The reason for this distinction is that 0x80
|
||||
* followed by optional zeros isn't padded.
|
||||
*/
|
||||
|
||||
int i2c_ASN1_INTEGER(ASN1_INTEGER *a, unsigned char **pp)
|
||||
{
|
||||
int pad = 0, ret, i, neg;
|
||||
unsigned char *p, *n, pb = 0;
|
||||
|
||||
if (a == NULL)
|
||||
return (0);
|
||||
neg = a->type & V_ASN1_NEG;
|
||||
if (a->length == 0)
|
||||
ret = 1;
|
||||
else {
|
||||
ret = a->length;
|
||||
i = a->data[0];
|
||||
if (ret == 1 && i == 0)
|
||||
neg = 0;
|
||||
if (!neg && (i > 127)) {
|
||||
pad = 1;
|
||||
pb = 0;
|
||||
} else if (neg) {
|
||||
if (i > 128) {
|
||||
pad = 1;
|
||||
pb = 0xFF;
|
||||
} else if (i == 128) {
|
||||
/*
|
||||
* Special case: if any other bytes non zero we pad:
|
||||
* otherwise we don't.
|
||||
*/
|
||||
for (i = 1; i < a->length; i++)
|
||||
if (a->data[i]) {
|
||||
pad = 1;
|
||||
pb = 0xFF;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
ret += pad;
|
||||
}
|
||||
if (pp == NULL)
|
||||
return (ret);
|
||||
p = *pp;
|
||||
|
||||
if (pad)
|
||||
*(p++) = pb;
|
||||
if (a->length == 0)
|
||||
*(p++) = 0;
|
||||
else if (!neg)
|
||||
OPENSSL_memcpy(p, a->data, (unsigned int)a->length);
|
||||
else {
|
||||
/* Begin at the end of the encoding */
|
||||
n = a->data + a->length - 1;
|
||||
p += a->length - 1;
|
||||
i = a->length;
|
||||
/* Copy zeros to destination as long as source is zero */
|
||||
while (!*n && i > 1) {
|
||||
*(p--) = 0;
|
||||
n--;
|
||||
i--;
|
||||
}
|
||||
/* Complement and increment next octet */
|
||||
*(p--) = ((*(n--)) ^ 0xff) + 1;
|
||||
i--;
|
||||
/* Complement any octets left */
|
||||
for (; i > 0; i--)
|
||||
*(p--) = *(n--) ^ 0xff;
|
||||
}
|
||||
|
||||
*pp += ret;
|
||||
return (ret);
|
||||
}
|
||||
|
||||
/* Convert just ASN1 INTEGER content octets to ASN1_INTEGER structure */
|
||||
|
||||
ASN1_INTEGER *c2i_ASN1_INTEGER(ASN1_INTEGER **a, const unsigned char **pp,
|
||||
long len)
|
||||
{
|
||||
ASN1_INTEGER *ret = NULL;
|
||||
const unsigned char *p, *pend;
|
||||
unsigned char *to, *s;
|
||||
int i;
|
||||
|
||||
/*
|
||||
* This function can handle lengths up to INT_MAX - 1, but the rest of the
|
||||
* legacy ASN.1 code mixes integer types, so avoid exposing it to
|
||||
* ASN1_INTEGERS with larger lengths.
|
||||
*/
|
||||
if (len < 0 || len > INT_MAX / 2) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_TOO_LONG);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ((a == NULL) || ((*a) == NULL)) {
|
||||
if ((ret = M_ASN1_INTEGER_new()) == NULL)
|
||||
return (NULL);
|
||||
ret->type = V_ASN1_INTEGER;
|
||||
} else
|
||||
ret = (*a);
|
||||
|
||||
p = *pp;
|
||||
pend = p + len;
|
||||
|
||||
/*
|
||||
* We must OPENSSL_malloc stuff, even for 0 bytes otherwise it signifies
|
||||
* a missing NULL parameter.
|
||||
*/
|
||||
s = (unsigned char *)OPENSSL_malloc((int)len + 1);
|
||||
if (s == NULL) {
|
||||
i = ERR_R_MALLOC_FAILURE;
|
||||
goto err;
|
||||
}
|
||||
to = s;
|
||||
if (!len) {
|
||||
/*
|
||||
* Strictly speaking this is an illegal INTEGER but we tolerate it.
|
||||
*/
|
||||
ret->type = V_ASN1_INTEGER;
|
||||
} else if (*p & 0x80) { /* a negative number */
|
||||
ret->type = V_ASN1_NEG_INTEGER;
|
||||
if ((*p == 0xff) && (len != 1)) {
|
||||
p++;
|
||||
len--;
|
||||
}
|
||||
i = len;
|
||||
p += i - 1;
|
||||
to += i - 1;
|
||||
while ((!*p) && i) {
|
||||
*(to--) = 0;
|
||||
i--;
|
||||
p--;
|
||||
}
|
||||
/*
|
||||
* Special case: if all zeros then the number will be of the form FF
|
||||
* followed by n zero bytes: this corresponds to 1 followed by n zero
|
||||
* bytes. We've already written n zeros so we just append an extra
|
||||
* one and set the first byte to a 1. This is treated separately
|
||||
* because it is the only case where the number of bytes is larger
|
||||
* than len.
|
||||
*/
|
||||
if (!i) {
|
||||
*s = 1;
|
||||
s[len] = 0;
|
||||
len++;
|
||||
} else {
|
||||
*(to--) = (*(p--) ^ 0xff) + 1;
|
||||
i--;
|
||||
for (; i > 0; i--)
|
||||
*(to--) = *(p--) ^ 0xff;
|
||||
}
|
||||
} else {
|
||||
ret->type = V_ASN1_INTEGER;
|
||||
if ((*p == 0) && (len != 1)) {
|
||||
p++;
|
||||
len--;
|
||||
}
|
||||
OPENSSL_memcpy(s, p, (int)len);
|
||||
}
|
||||
|
||||
if (ret->data != NULL)
|
||||
OPENSSL_free(ret->data);
|
||||
ret->data = s;
|
||||
ret->length = (int)len;
|
||||
if (a != NULL)
|
||||
(*a) = ret;
|
||||
*pp = pend;
|
||||
return (ret);
|
||||
err:
|
||||
OPENSSL_PUT_ERROR(ASN1, i);
|
||||
if ((ret != NULL) && ((a == NULL) || (*a != ret)))
|
||||
M_ASN1_INTEGER_free(ret);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
int ASN1_INTEGER_set(ASN1_INTEGER *a, long v)
|
||||
{
|
||||
if (v >= 0) {
|
||||
return ASN1_INTEGER_set_uint64(a, (uint64_t) v);
|
||||
}
|
||||
|
||||
if (!ASN1_INTEGER_set_uint64(a, 0 - (uint64_t) v)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
a->type = V_ASN1_NEG_INTEGER;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ASN1_INTEGER_set_uint64(ASN1_INTEGER *out, uint64_t v)
|
||||
{
|
||||
uint8_t *const newdata = OPENSSL_malloc(sizeof(uint64_t));
|
||||
if (newdata == NULL) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
OPENSSL_free(out->data);
|
||||
out->data = newdata;
|
||||
v = CRYPTO_bswap8(v);
|
||||
memcpy(out->data, &v, sizeof(v));
|
||||
|
||||
out->type = V_ASN1_INTEGER;
|
||||
|
||||
size_t leading_zeros;
|
||||
for (leading_zeros = 0; leading_zeros < sizeof(uint64_t) - 1;
|
||||
leading_zeros++) {
|
||||
if (out->data[leading_zeros] != 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
out->length = sizeof(uint64_t) - leading_zeros;
|
||||
OPENSSL_memmove(out->data, out->data + leading_zeros, out->length);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
long ASN1_INTEGER_get(const ASN1_INTEGER *a)
|
||||
{
|
||||
int neg = 0, i;
|
||||
|
||||
if (a == NULL)
|
||||
return (0L);
|
||||
i = a->type;
|
||||
if (i == V_ASN1_NEG_INTEGER)
|
||||
neg = 1;
|
||||
else if (i != V_ASN1_INTEGER)
|
||||
return -1;
|
||||
|
||||
OPENSSL_STATIC_ASSERT(sizeof(uint64_t) >= sizeof(long),
|
||||
"long larger than uint64_t");
|
||||
|
||||
if (a->length > (int)sizeof(uint64_t)) {
|
||||
/* hmm... a bit ugly, return all ones */
|
||||
return -1;
|
||||
}
|
||||
|
||||
uint64_t r64 = 0;
|
||||
if (a->data != NULL) {
|
||||
for (i = 0; i < a->length; i++) {
|
||||
r64 <<= 8;
|
||||
r64 |= (unsigned char)a->data[i];
|
||||
}
|
||||
|
||||
if (r64 > LONG_MAX) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
long r = (long) r64;
|
||||
if (neg)
|
||||
r = -r;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
ASN1_INTEGER *BN_to_ASN1_INTEGER(const BIGNUM *bn, ASN1_INTEGER *ai)
|
||||
{
|
||||
ASN1_INTEGER *ret;
|
||||
int len, j;
|
||||
|
||||
if (ai == NULL)
|
||||
ret = M_ASN1_INTEGER_new();
|
||||
else
|
||||
ret = ai;
|
||||
if (ret == NULL) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR);
|
||||
goto err;
|
||||
}
|
||||
if (BN_is_negative(bn) && !BN_is_zero(bn))
|
||||
ret->type = V_ASN1_NEG_INTEGER;
|
||||
else
|
||||
ret->type = V_ASN1_INTEGER;
|
||||
j = BN_num_bits(bn);
|
||||
len = ((j == 0) ? 0 : ((j / 8) + 1));
|
||||
if (ret->length < len + 4) {
|
||||
unsigned char *new_data = OPENSSL_realloc(ret->data, len + 4);
|
||||
if (!new_data) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
ret->data = new_data;
|
||||
}
|
||||
ret->length = BN_bn2bin(bn, ret->data);
|
||||
/* Correct zero case */
|
||||
if (!ret->length) {
|
||||
ret->data[0] = 0;
|
||||
ret->length = 1;
|
||||
}
|
||||
return (ret);
|
||||
err:
|
||||
if (ret != ai)
|
||||
M_ASN1_INTEGER_free(ret);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
BIGNUM *ASN1_INTEGER_to_BN(const ASN1_INTEGER *ai, BIGNUM *bn)
|
||||
{
|
||||
BIGNUM *ret;
|
||||
|
||||
if ((ret = BN_bin2bn(ai->data, ai->length, bn)) == NULL)
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_BN_LIB);
|
||||
else if (ai->type == V_ASN1_NEG_INTEGER)
|
||||
BN_set_negative(ret, 1);
|
||||
return (ret);
|
||||
}
|
||||
+305
@@ -0,0 +1,305 @@
|
||||
/* Copyright (C) 1995-1998 Eric Young ([email protected])
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young ([email protected]).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson ([email protected]).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young ([email protected])"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson ([email protected])"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.] */
|
||||
|
||||
#include <openssl_grpc/asn1.h>
|
||||
|
||||
#include <limits.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <openssl_grpc/bytestring.h>
|
||||
#include <openssl_grpc/err.h>
|
||||
#include <openssl_grpc/mem.h>
|
||||
|
||||
#include "asn1_locl.h"
|
||||
#include "../bytestring/internal.h"
|
||||
|
||||
static int is_printable(uint32_t value);
|
||||
|
||||
/*
|
||||
* These functions take a string in UTF8, ASCII or multibyte form and a mask
|
||||
* of permissible ASN1 string types. It then works out the minimal type
|
||||
* (using the order Printable < IA5 < T61 < BMP < Universal < UTF8) and
|
||||
* creates a string of the correct type with the supplied data. Yes this is
|
||||
* horrible: it has to be :-( The 'ncopy' form checks minimum and maximum
|
||||
* size limits too.
|
||||
*/
|
||||
|
||||
int ASN1_mbstring_copy(ASN1_STRING **out, const unsigned char *in, int len,
|
||||
int inform, unsigned long mask)
|
||||
{
|
||||
return ASN1_mbstring_ncopy(out, in, len, inform, mask, 0, 0);
|
||||
}
|
||||
|
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, INVALID_BMPSTRING)
|
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, INVALID_UNIVERSALSTRING)
|
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, INVALID_UTF8STRING)
|
||||
|
||||
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;
|
||||
char free_out;
|
||||
ASN1_STRING *dest;
|
||||
size_t nchar = 0;
|
||||
char strbuf[32];
|
||||
if (len == -1)
|
||||
len = strlen((const char *)in);
|
||||
if (!mask)
|
||||
mask = DIRSTRING_TYPE;
|
||||
|
||||
int (*decode_func)(CBS *, uint32_t*);
|
||||
int error;
|
||||
switch (inform) {
|
||||
case MBSTRING_BMP:
|
||||
decode_func = cbs_get_ucs2_be;
|
||||
error = ASN1_R_INVALID_BMPSTRING;
|
||||
break;
|
||||
|
||||
case MBSTRING_UNIV:
|
||||
decode_func = cbs_get_utf32_be;
|
||||
error = ASN1_R_INVALID_UNIVERSALSTRING;
|
||||
break;
|
||||
|
||||
case MBSTRING_UTF8:
|
||||
decode_func = cbs_get_utf8;
|
||||
error = ASN1_R_INVALID_UTF8STRING;
|
||||
break;
|
||||
|
||||
case MBSTRING_ASC:
|
||||
decode_func = cbs_get_latin1;
|
||||
error = ERR_R_INTERNAL_ERROR; // Latin-1 inputs are never invalid.
|
||||
break;
|
||||
|
||||
default:
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_UNKNOWN_FORMAT);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Check |minsize| and |maxsize| and work out the minimal type, if any. */
|
||||
CBS cbs;
|
||||
CBS_init(&cbs, in, len);
|
||||
size_t utf8_len = 0;
|
||||
while (CBS_len(&cbs) != 0) {
|
||||
uint32_t c;
|
||||
if (!decode_func(&cbs, &c)) {
|
||||
OPENSSL_PUT_ERROR(ASN1, error);
|
||||
return -1;
|
||||
}
|
||||
if (nchar == 0 &&
|
||||
(inform == MBSTRING_BMP || inform == MBSTRING_UNIV) &&
|
||||
c == 0xfeff) {
|
||||
/* Reject byte-order mark. We could drop it but that would mean
|
||||
* adding ambiguity around whether a BOM was included or not when
|
||||
* matching strings.
|
||||
*
|
||||
* For a little-endian UCS-2 string, the BOM will appear as 0xfffe
|
||||
* and will be rejected as noncharacter, below. */
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_CHARACTERS);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Update which output formats are still possible. */
|
||||
if ((mask & B_ASN1_PRINTABLESTRING) && !is_printable(c)) {
|
||||
mask &= ~B_ASN1_PRINTABLESTRING;
|
||||
}
|
||||
if ((mask & B_ASN1_IA5STRING) && (c > 127)) {
|
||||
mask &= ~B_ASN1_IA5STRING;
|
||||
}
|
||||
if ((mask & B_ASN1_T61STRING) && (c > 0xff)) {
|
||||
mask &= ~B_ASN1_T61STRING;
|
||||
}
|
||||
if ((mask & B_ASN1_BMPSTRING) && (c > 0xffff)) {
|
||||
mask &= ~B_ASN1_BMPSTRING;
|
||||
}
|
||||
if (!mask) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_CHARACTERS);
|
||||
return -1;
|
||||
}
|
||||
|
||||
nchar++;
|
||||
utf8_len += cbb_get_utf8_len(c);
|
||||
}
|
||||
|
||||
if (minsize > 0 && nchar < (size_t)minsize) {
|
||||
OPENSSL_PUT_ERROR(ASN1, 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 > (size_t)maxsize) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_STRING_TOO_LONG);
|
||||
BIO_snprintf(strbuf, sizeof strbuf, "%ld", maxsize);
|
||||
ERR_add_error_data(2, "maxsize=", strbuf);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Now work out output format and string type */
|
||||
int (*encode_func)(CBB *, uint32_t) = cbb_add_latin1;
|
||||
size_t size_estimate = nchar;
|
||||
int outform = MBSTRING_ASC;
|
||||
if (mask & B_ASN1_PRINTABLESTRING) {
|
||||
str_type = V_ASN1_PRINTABLESTRING;
|
||||
} else if (mask & B_ASN1_IA5STRING) {
|
||||
str_type = V_ASN1_IA5STRING;
|
||||
} else if (mask & B_ASN1_T61STRING) {
|
||||
str_type = V_ASN1_T61STRING;
|
||||
} else if (mask & B_ASN1_BMPSTRING) {
|
||||
str_type = V_ASN1_BMPSTRING;
|
||||
outform = MBSTRING_BMP;
|
||||
encode_func = cbb_add_ucs2_be;
|
||||
size_estimate = 2 * nchar;
|
||||
} else if (mask & B_ASN1_UNIVERSALSTRING) {
|
||||
str_type = V_ASN1_UNIVERSALSTRING;
|
||||
encode_func = cbb_add_utf32_be;
|
||||
size_estimate = 4 * nchar;
|
||||
outform = MBSTRING_UNIV;
|
||||
} else {
|
||||
str_type = V_ASN1_UTF8STRING;
|
||||
outform = MBSTRING_UTF8;
|
||||
encode_func = cbb_add_utf8;
|
||||
size_estimate = utf8_len;
|
||||
}
|
||||
|
||||
if (!out)
|
||||
return str_type;
|
||||
if (*out) {
|
||||
free_out = 0;
|
||||
dest = *out;
|
||||
if (dest->data) {
|
||||
dest->length = 0;
|
||||
OPENSSL_free(dest->data);
|
||||
dest->data = NULL;
|
||||
}
|
||||
dest->type = str_type;
|
||||
} else {
|
||||
free_out = 1;
|
||||
dest = ASN1_STRING_type_new(str_type);
|
||||
if (!dest) {
|
||||
OPENSSL_PUT_ERROR(ASN1, 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)) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
|
||||
return -1;
|
||||
}
|
||||
return str_type;
|
||||
}
|
||||
|
||||
CBB cbb;
|
||||
if (!CBB_init(&cbb, size_estimate + 1)) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
CBS_init(&cbs, in, len);
|
||||
while (CBS_len(&cbs) != 0) {
|
||||
uint32_t c;
|
||||
if (!decode_func(&cbs, &c) ||
|
||||
!encode_func(&cbb, c)) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
uint8_t *data = NULL;
|
||||
size_t data_len;
|
||||
if (/* OpenSSL historically NUL-terminated this value with a single byte,
|
||||
* even for |MBSTRING_BMP| and |MBSTRING_UNIV|. */
|
||||
!CBB_add_u8(&cbb, 0) ||
|
||||
!CBB_finish(&cbb, &data, &data_len) ||
|
||||
data_len < 1 ||
|
||||
data_len > INT_MAX) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_INTERNAL_ERROR);
|
||||
OPENSSL_free(data);
|
||||
goto err;
|
||||
}
|
||||
dest->length = (int)(data_len - 1);
|
||||
dest->data = data;
|
||||
return str_type;
|
||||
|
||||
err:
|
||||
if (free_out)
|
||||
ASN1_STRING_free(dest);
|
||||
CBB_cleanup(&cbb);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Return 1 if the character is permitted in a PrintableString */
|
||||
static int is_printable(uint32_t value)
|
||||
{
|
||||
int ch;
|
||||
if (value > 0x7f)
|
||||
return 0;
|
||||
ch = (int)value;
|
||||
/*
|
||||
* Note: we can't use 'isalnum' because certain accented characters may
|
||||
* count as alphanumeric in some environments.
|
||||
*/
|
||||
if ((ch >= 'a') && (ch <= 'z'))
|
||||
return 1;
|
||||
if ((ch >= 'A') && (ch <= 'Z'))
|
||||
return 1;
|
||||
if ((ch >= '0') && (ch <= '9'))
|
||||
return 1;
|
||||
if ((ch == ' ') || strchr("'()+,-./:=?", ch))
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
+305
@@ -0,0 +1,305 @@
|
||||
/* Copyright (C) 1995-1998 Eric Young ([email protected])
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young ([email protected]).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson ([email protected]).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young ([email protected])"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson ([email protected])"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.] */
|
||||
|
||||
#include <openssl/asn1.h>
|
||||
|
||||
#include <limits.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <openssl/bytestring.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/mem.h>
|
||||
|
||||
#include "asn1_locl.h"
|
||||
#include "../bytestring/internal.h"
|
||||
|
||||
static int is_printable(uint32_t value);
|
||||
|
||||
/*
|
||||
* These functions take a string in UTF8, ASCII or multibyte form and a mask
|
||||
* of permissible ASN1 string types. It then works out the minimal type
|
||||
* (using the order Printable < IA5 < T61 < BMP < Universal < UTF8) and
|
||||
* creates a string of the correct type with the supplied data. Yes this is
|
||||
* horrible: it has to be :-( The 'ncopy' form checks minimum and maximum
|
||||
* size limits too.
|
||||
*/
|
||||
|
||||
int ASN1_mbstring_copy(ASN1_STRING **out, const unsigned char *in, int len,
|
||||
int inform, unsigned long mask)
|
||||
{
|
||||
return ASN1_mbstring_ncopy(out, in, len, inform, mask, 0, 0);
|
||||
}
|
||||
|
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, INVALID_BMPSTRING)
|
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, INVALID_UNIVERSALSTRING)
|
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, INVALID_UTF8STRING)
|
||||
|
||||
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;
|
||||
char free_out;
|
||||
ASN1_STRING *dest;
|
||||
size_t nchar = 0;
|
||||
char strbuf[32];
|
||||
if (len == -1)
|
||||
len = strlen((const char *)in);
|
||||
if (!mask)
|
||||
mask = DIRSTRING_TYPE;
|
||||
|
||||
int (*decode_func)(CBS *, uint32_t*);
|
||||
int error;
|
||||
switch (inform) {
|
||||
case MBSTRING_BMP:
|
||||
decode_func = cbs_get_ucs2_be;
|
||||
error = ASN1_R_INVALID_BMPSTRING;
|
||||
break;
|
||||
|
||||
case MBSTRING_UNIV:
|
||||
decode_func = cbs_get_utf32_be;
|
||||
error = ASN1_R_INVALID_UNIVERSALSTRING;
|
||||
break;
|
||||
|
||||
case MBSTRING_UTF8:
|
||||
decode_func = cbs_get_utf8;
|
||||
error = ASN1_R_INVALID_UTF8STRING;
|
||||
break;
|
||||
|
||||
case MBSTRING_ASC:
|
||||
decode_func = cbs_get_latin1;
|
||||
error = ERR_R_INTERNAL_ERROR; // Latin-1 inputs are never invalid.
|
||||
break;
|
||||
|
||||
default:
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_UNKNOWN_FORMAT);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Check |minsize| and |maxsize| and work out the minimal type, if any. */
|
||||
CBS cbs;
|
||||
CBS_init(&cbs, in, len);
|
||||
size_t utf8_len = 0;
|
||||
while (CBS_len(&cbs) != 0) {
|
||||
uint32_t c;
|
||||
if (!decode_func(&cbs, &c)) {
|
||||
OPENSSL_PUT_ERROR(ASN1, error);
|
||||
return -1;
|
||||
}
|
||||
if (nchar == 0 &&
|
||||
(inform == MBSTRING_BMP || inform == MBSTRING_UNIV) &&
|
||||
c == 0xfeff) {
|
||||
/* Reject byte-order mark. We could drop it but that would mean
|
||||
* adding ambiguity around whether a BOM was included or not when
|
||||
* matching strings.
|
||||
*
|
||||
* For a little-endian UCS-2 string, the BOM will appear as 0xfffe
|
||||
* and will be rejected as noncharacter, below. */
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_CHARACTERS);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Update which output formats are still possible. */
|
||||
if ((mask & B_ASN1_PRINTABLESTRING) && !is_printable(c)) {
|
||||
mask &= ~B_ASN1_PRINTABLESTRING;
|
||||
}
|
||||
if ((mask & B_ASN1_IA5STRING) && (c > 127)) {
|
||||
mask &= ~B_ASN1_IA5STRING;
|
||||
}
|
||||
if ((mask & B_ASN1_T61STRING) && (c > 0xff)) {
|
||||
mask &= ~B_ASN1_T61STRING;
|
||||
}
|
||||
if ((mask & B_ASN1_BMPSTRING) && (c > 0xffff)) {
|
||||
mask &= ~B_ASN1_BMPSTRING;
|
||||
}
|
||||
if (!mask) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_CHARACTERS);
|
||||
return -1;
|
||||
}
|
||||
|
||||
nchar++;
|
||||
utf8_len += cbb_get_utf8_len(c);
|
||||
}
|
||||
|
||||
if (minsize > 0 && nchar < (size_t)minsize) {
|
||||
OPENSSL_PUT_ERROR(ASN1, 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 > (size_t)maxsize) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_STRING_TOO_LONG);
|
||||
BIO_snprintf(strbuf, sizeof strbuf, "%ld", maxsize);
|
||||
ERR_add_error_data(2, "maxsize=", strbuf);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Now work out output format and string type */
|
||||
int (*encode_func)(CBB *, uint32_t) = cbb_add_latin1;
|
||||
size_t size_estimate = nchar;
|
||||
int outform = MBSTRING_ASC;
|
||||
if (mask & B_ASN1_PRINTABLESTRING) {
|
||||
str_type = V_ASN1_PRINTABLESTRING;
|
||||
} else if (mask & B_ASN1_IA5STRING) {
|
||||
str_type = V_ASN1_IA5STRING;
|
||||
} else if (mask & B_ASN1_T61STRING) {
|
||||
str_type = V_ASN1_T61STRING;
|
||||
} else if (mask & B_ASN1_BMPSTRING) {
|
||||
str_type = V_ASN1_BMPSTRING;
|
||||
outform = MBSTRING_BMP;
|
||||
encode_func = cbb_add_ucs2_be;
|
||||
size_estimate = 2 * nchar;
|
||||
} else if (mask & B_ASN1_UNIVERSALSTRING) {
|
||||
str_type = V_ASN1_UNIVERSALSTRING;
|
||||
encode_func = cbb_add_utf32_be;
|
||||
size_estimate = 4 * nchar;
|
||||
outform = MBSTRING_UNIV;
|
||||
} else {
|
||||
str_type = V_ASN1_UTF8STRING;
|
||||
outform = MBSTRING_UTF8;
|
||||
encode_func = cbb_add_utf8;
|
||||
size_estimate = utf8_len;
|
||||
}
|
||||
|
||||
if (!out)
|
||||
return str_type;
|
||||
if (*out) {
|
||||
free_out = 0;
|
||||
dest = *out;
|
||||
if (dest->data) {
|
||||
dest->length = 0;
|
||||
OPENSSL_free(dest->data);
|
||||
dest->data = NULL;
|
||||
}
|
||||
dest->type = str_type;
|
||||
} else {
|
||||
free_out = 1;
|
||||
dest = ASN1_STRING_type_new(str_type);
|
||||
if (!dest) {
|
||||
OPENSSL_PUT_ERROR(ASN1, 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)) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
|
||||
return -1;
|
||||
}
|
||||
return str_type;
|
||||
}
|
||||
|
||||
CBB cbb;
|
||||
if (!CBB_init(&cbb, size_estimate + 1)) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
CBS_init(&cbs, in, len);
|
||||
while (CBS_len(&cbs) != 0) {
|
||||
uint32_t c;
|
||||
if (!decode_func(&cbs, &c) ||
|
||||
!encode_func(&cbb, c)) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
uint8_t *data = NULL;
|
||||
size_t data_len;
|
||||
if (/* OpenSSL historically NUL-terminated this value with a single byte,
|
||||
* even for |MBSTRING_BMP| and |MBSTRING_UNIV|. */
|
||||
!CBB_add_u8(&cbb, 0) ||
|
||||
!CBB_finish(&cbb, &data, &data_len) ||
|
||||
data_len < 1 ||
|
||||
data_len > INT_MAX) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_INTERNAL_ERROR);
|
||||
OPENSSL_free(data);
|
||||
goto err;
|
||||
}
|
||||
dest->length = (int)(data_len - 1);
|
||||
dest->data = data;
|
||||
return str_type;
|
||||
|
||||
err:
|
||||
if (free_out)
|
||||
ASN1_STRING_free(dest);
|
||||
CBB_cleanup(&cbb);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Return 1 if the character is permitted in a PrintableString */
|
||||
static int is_printable(uint32_t value)
|
||||
{
|
||||
int ch;
|
||||
if (value > 0x7f)
|
||||
return 0;
|
||||
ch = (int)value;
|
||||
/*
|
||||
* Note: we can't use 'isalnum' because certain accented characters may
|
||||
* count as alphanumeric in some environments.
|
||||
*/
|
||||
if ((ch >= 'a') && (ch <= 'z'))
|
||||
return 1;
|
||||
if ((ch >= 'A') && (ch <= 'Z'))
|
||||
return 1;
|
||||
if ((ch >= '0') && (ch <= '9'))
|
||||
return 1;
|
||||
if ((ch == ' ') || strchr("'()+,-./:=?", ch))
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
+286
@@ -0,0 +1,286 @@
|
||||
/* Copyright (C) 1995-1998 Eric Young ([email protected])
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young ([email protected]).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson ([email protected]).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young ([email protected])"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson ([email protected])"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.] */
|
||||
|
||||
#include <openssl_grpc/asn1.h>
|
||||
|
||||
#include <limits.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <openssl_grpc/err.h>
|
||||
#include <openssl_grpc/mem.h>
|
||||
#include <openssl_grpc/obj.h>
|
||||
|
||||
#include "../internal.h"
|
||||
|
||||
|
||||
int i2d_ASN1_OBJECT(ASN1_OBJECT *a, unsigned char **pp)
|
||||
{
|
||||
unsigned char *p, *allocated = NULL;
|
||||
int objsize;
|
||||
|
||||
if ((a == NULL) || (a->data == NULL))
|
||||
return (0);
|
||||
|
||||
objsize = ASN1_object_size(0, a->length, V_ASN1_OBJECT);
|
||||
if (pp == NULL || objsize == -1)
|
||||
return objsize;
|
||||
|
||||
if (*pp == NULL) {
|
||||
if ((p = allocated = OPENSSL_malloc(objsize)) == NULL) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
p = *pp;
|
||||
}
|
||||
|
||||
ASN1_put_object(&p, 0, a->length, V_ASN1_OBJECT, V_ASN1_UNIVERSAL);
|
||||
OPENSSL_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 i2t_ASN1_OBJECT(char *buf, int buf_len, ASN1_OBJECT *a)
|
||||
{
|
||||
return OBJ_obj2txt(buf, buf_len, a, 0);
|
||||
}
|
||||
|
||||
int i2a_ASN1_OBJECT(BIO *bp, ASN1_OBJECT *a)
|
||||
{
|
||||
char buf[80], *p = buf;
|
||||
int i;
|
||||
|
||||
if ((a == NULL) || (a->data == NULL))
|
||||
return (BIO_write(bp, "NULL", 4));
|
||||
i = i2t_ASN1_OBJECT(buf, sizeof buf, a);
|
||||
if (i > (int)(sizeof(buf) - 1)) {
|
||||
p = OPENSSL_malloc(i + 1);
|
||||
if (!p)
|
||||
return -1;
|
||||
i2t_ASN1_OBJECT(p, i + 1, a);
|
||||
}
|
||||
if (i <= 0)
|
||||
return BIO_write(bp, "<INVALID>", 9);
|
||||
BIO_write(bp, p, i);
|
||||
if (p != buf)
|
||||
OPENSSL_free(p);
|
||||
return (i);
|
||||
}
|
||||
|
||||
ASN1_OBJECT *d2i_ASN1_OBJECT(ASN1_OBJECT **a, const unsigned char **pp,
|
||||
long length)
|
||||
{
|
||||
const unsigned char *p;
|
||||
long len;
|
||||
int tag, xclass;
|
||||
int inf, i;
|
||||
ASN1_OBJECT *ret = NULL;
|
||||
p = *pp;
|
||||
inf = ASN1_get_object(&p, &len, &tag, &xclass, length);
|
||||
if (inf & 0x80) {
|
||||
i = ASN1_R_BAD_OBJECT_HEADER;
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (tag != V_ASN1_OBJECT) {
|
||||
i = ASN1_R_EXPECTING_AN_OBJECT;
|
||||
goto err;
|
||||
}
|
||||
ret = c2i_ASN1_OBJECT(a, &p, len);
|
||||
if (ret)
|
||||
*pp = p;
|
||||
return ret;
|
||||
err:
|
||||
OPENSSL_PUT_ERROR(ASN1, i);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
ASN1_OBJECT *c2i_ASN1_OBJECT(ASN1_OBJECT **a, const unsigned char **pp,
|
||||
long len)
|
||||
{
|
||||
ASN1_OBJECT *ret = NULL;
|
||||
const unsigned char *p;
|
||||
unsigned char *data;
|
||||
int i, length;
|
||||
|
||||
/*
|
||||
* Sanity check OID encoding. Need at least one content octet. MSB must
|
||||
* be clear in the last octet. can't have leading 0x80 in subidentifiers,
|
||||
* see: X.690 8.19.2
|
||||
*/
|
||||
if (len <= 0 || len > INT_MAX || pp == NULL || (p = *pp) == NULL ||
|
||||
p[len - 1] & 0x80) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_OBJECT_ENCODING);
|
||||
return NULL;
|
||||
}
|
||||
/* Now 0 < len <= INT_MAX, so the cast is safe. */
|
||||
length = (int)len;
|
||||
for (i = 0; i < length; i++, p++) {
|
||||
if (*p == 0x80 && (!i || !(p[-1] & 0x80))) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_OBJECT_ENCODING);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* only the ASN1_OBJECTs from the 'table' will have values for ->sn or
|
||||
* ->ln
|
||||
*/
|
||||
if ((a == NULL) || ((*a) == NULL) ||
|
||||
!((*a)->flags & ASN1_OBJECT_FLAG_DYNAMIC)) {
|
||||
if ((ret = ASN1_OBJECT_new()) == NULL)
|
||||
return (NULL);
|
||||
} else
|
||||
ret = (*a);
|
||||
|
||||
p = *pp;
|
||||
/* detach data from object */
|
||||
data = (unsigned char *)ret->data;
|
||||
ret->data = NULL;
|
||||
/* once detached we can change it */
|
||||
if ((data == NULL) || (ret->length < length)) {
|
||||
ret->length = 0;
|
||||
if (data != NULL)
|
||||
OPENSSL_free(data);
|
||||
data = (unsigned char *)OPENSSL_malloc(length);
|
||||
if (data == NULL) {
|
||||
i = ERR_R_MALLOC_FAILURE;
|
||||
goto err;
|
||||
}
|
||||
ret->flags |= ASN1_OBJECT_FLAG_DYNAMIC_DATA;
|
||||
}
|
||||
OPENSSL_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:
|
||||
OPENSSL_PUT_ERROR(ASN1, i);
|
||||
if ((ret != NULL) && ((a == NULL) || (*a != ret)))
|
||||
ASN1_OBJECT_free(ret);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
ASN1_OBJECT *ASN1_OBJECT_new(void)
|
||||
{
|
||||
ASN1_OBJECT *ret;
|
||||
|
||||
ret = (ASN1_OBJECT *)OPENSSL_malloc(sizeof(ASN1_OBJECT));
|
||||
if (ret == NULL) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
|
||||
return (NULL);
|
||||
}
|
||||
ret->length = 0;
|
||||
ret->data = NULL;
|
||||
ret->nid = 0;
|
||||
ret->sn = NULL;
|
||||
ret->ln = NULL;
|
||||
ret->flags = ASN1_OBJECT_FLAG_DYNAMIC;
|
||||
return (ret);
|
||||
}
|
||||
|
||||
void ASN1_OBJECT_free(ASN1_OBJECT *a)
|
||||
{
|
||||
if (a == NULL)
|
||||
return;
|
||||
if (a->flags & ASN1_OBJECT_FLAG_DYNAMIC_STRINGS) {
|
||||
#ifndef CONST_STRICT /* disable purely for compile-time strict
|
||||
* const checking. Doing this on a "real"
|
||||
* compile will cause memory leaks */
|
||||
if (a->sn != NULL)
|
||||
OPENSSL_free((void *)a->sn);
|
||||
if (a->ln != NULL)
|
||||
OPENSSL_free((void *)a->ln);
|
||||
#endif
|
||||
a->sn = a->ln = NULL;
|
||||
}
|
||||
if (a->flags & ASN1_OBJECT_FLAG_DYNAMIC_DATA) {
|
||||
if (a->data != NULL)
|
||||
OPENSSL_free((void *)a->data);
|
||||
a->data = NULL;
|
||||
a->length = 0;
|
||||
}
|
||||
if (a->flags & ASN1_OBJECT_FLAG_DYNAMIC)
|
||||
OPENSSL_free(a);
|
||||
}
|
||||
|
||||
ASN1_OBJECT *ASN1_OBJECT_create(int nid, unsigned char *data, int len,
|
||||
const char *sn, const char *ln)
|
||||
{
|
||||
ASN1_OBJECT o;
|
||||
|
||||
o.sn = sn;
|
||||
o.ln = ln;
|
||||
o.data = data;
|
||||
o.nid = nid;
|
||||
o.length = len;
|
||||
o.flags = ASN1_OBJECT_FLAG_DYNAMIC | ASN1_OBJECT_FLAG_DYNAMIC_STRINGS |
|
||||
ASN1_OBJECT_FLAG_DYNAMIC_DATA;
|
||||
return (OBJ_dup(&o));
|
||||
}
|
||||
@@ -0,0 +1,286 @@
|
||||
/* Copyright (C) 1995-1998 Eric Young ([email protected])
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young ([email protected]).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson ([email protected]).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young ([email protected])"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson ([email protected])"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.] */
|
||||
|
||||
#include <openssl/asn1.h>
|
||||
|
||||
#include <limits.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/mem.h>
|
||||
#include <openssl/obj.h>
|
||||
|
||||
#include "../internal.h"
|
||||
|
||||
|
||||
int i2d_ASN1_OBJECT(ASN1_OBJECT *a, unsigned char **pp)
|
||||
{
|
||||
unsigned char *p, *allocated = NULL;
|
||||
int objsize;
|
||||
|
||||
if ((a == NULL) || (a->data == NULL))
|
||||
return (0);
|
||||
|
||||
objsize = ASN1_object_size(0, a->length, V_ASN1_OBJECT);
|
||||
if (pp == NULL || objsize == -1)
|
||||
return objsize;
|
||||
|
||||
if (*pp == NULL) {
|
||||
if ((p = allocated = OPENSSL_malloc(objsize)) == NULL) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
p = *pp;
|
||||
}
|
||||
|
||||
ASN1_put_object(&p, 0, a->length, V_ASN1_OBJECT, V_ASN1_UNIVERSAL);
|
||||
OPENSSL_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 i2t_ASN1_OBJECT(char *buf, int buf_len, ASN1_OBJECT *a)
|
||||
{
|
||||
return OBJ_obj2txt(buf, buf_len, a, 0);
|
||||
}
|
||||
|
||||
int i2a_ASN1_OBJECT(BIO *bp, ASN1_OBJECT *a)
|
||||
{
|
||||
char buf[80], *p = buf;
|
||||
int i;
|
||||
|
||||
if ((a == NULL) || (a->data == NULL))
|
||||
return (BIO_write(bp, "NULL", 4));
|
||||
i = i2t_ASN1_OBJECT(buf, sizeof buf, a);
|
||||
if (i > (int)(sizeof(buf) - 1)) {
|
||||
p = OPENSSL_malloc(i + 1);
|
||||
if (!p)
|
||||
return -1;
|
||||
i2t_ASN1_OBJECT(p, i + 1, a);
|
||||
}
|
||||
if (i <= 0)
|
||||
return BIO_write(bp, "<INVALID>", 9);
|
||||
BIO_write(bp, p, i);
|
||||
if (p != buf)
|
||||
OPENSSL_free(p);
|
||||
return (i);
|
||||
}
|
||||
|
||||
ASN1_OBJECT *d2i_ASN1_OBJECT(ASN1_OBJECT **a, const unsigned char **pp,
|
||||
long length)
|
||||
{
|
||||
const unsigned char *p;
|
||||
long len;
|
||||
int tag, xclass;
|
||||
int inf, i;
|
||||
ASN1_OBJECT *ret = NULL;
|
||||
p = *pp;
|
||||
inf = ASN1_get_object(&p, &len, &tag, &xclass, length);
|
||||
if (inf & 0x80) {
|
||||
i = ASN1_R_BAD_OBJECT_HEADER;
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (tag != V_ASN1_OBJECT) {
|
||||
i = ASN1_R_EXPECTING_AN_OBJECT;
|
||||
goto err;
|
||||
}
|
||||
ret = c2i_ASN1_OBJECT(a, &p, len);
|
||||
if (ret)
|
||||
*pp = p;
|
||||
return ret;
|
||||
err:
|
||||
OPENSSL_PUT_ERROR(ASN1, i);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
ASN1_OBJECT *c2i_ASN1_OBJECT(ASN1_OBJECT **a, const unsigned char **pp,
|
||||
long len)
|
||||
{
|
||||
ASN1_OBJECT *ret = NULL;
|
||||
const unsigned char *p;
|
||||
unsigned char *data;
|
||||
int i, length;
|
||||
|
||||
/*
|
||||
* Sanity check OID encoding. Need at least one content octet. MSB must
|
||||
* be clear in the last octet. can't have leading 0x80 in subidentifiers,
|
||||
* see: X.690 8.19.2
|
||||
*/
|
||||
if (len <= 0 || len > INT_MAX || pp == NULL || (p = *pp) == NULL ||
|
||||
p[len - 1] & 0x80) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_OBJECT_ENCODING);
|
||||
return NULL;
|
||||
}
|
||||
/* Now 0 < len <= INT_MAX, so the cast is safe. */
|
||||
length = (int)len;
|
||||
for (i = 0; i < length; i++, p++) {
|
||||
if (*p == 0x80 && (!i || !(p[-1] & 0x80))) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_OBJECT_ENCODING);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* only the ASN1_OBJECTs from the 'table' will have values for ->sn or
|
||||
* ->ln
|
||||
*/
|
||||
if ((a == NULL) || ((*a) == NULL) ||
|
||||
!((*a)->flags & ASN1_OBJECT_FLAG_DYNAMIC)) {
|
||||
if ((ret = ASN1_OBJECT_new()) == NULL)
|
||||
return (NULL);
|
||||
} else
|
||||
ret = (*a);
|
||||
|
||||
p = *pp;
|
||||
/* detach data from object */
|
||||
data = (unsigned char *)ret->data;
|
||||
ret->data = NULL;
|
||||
/* once detached we can change it */
|
||||
if ((data == NULL) || (ret->length < length)) {
|
||||
ret->length = 0;
|
||||
if (data != NULL)
|
||||
OPENSSL_free(data);
|
||||
data = (unsigned char *)OPENSSL_malloc(length);
|
||||
if (data == NULL) {
|
||||
i = ERR_R_MALLOC_FAILURE;
|
||||
goto err;
|
||||
}
|
||||
ret->flags |= ASN1_OBJECT_FLAG_DYNAMIC_DATA;
|
||||
}
|
||||
OPENSSL_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:
|
||||
OPENSSL_PUT_ERROR(ASN1, i);
|
||||
if ((ret != NULL) && ((a == NULL) || (*a != ret)))
|
||||
ASN1_OBJECT_free(ret);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
ASN1_OBJECT *ASN1_OBJECT_new(void)
|
||||
{
|
||||
ASN1_OBJECT *ret;
|
||||
|
||||
ret = (ASN1_OBJECT *)OPENSSL_malloc(sizeof(ASN1_OBJECT));
|
||||
if (ret == NULL) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
|
||||
return (NULL);
|
||||
}
|
||||
ret->length = 0;
|
||||
ret->data = NULL;
|
||||
ret->nid = 0;
|
||||
ret->sn = NULL;
|
||||
ret->ln = NULL;
|
||||
ret->flags = ASN1_OBJECT_FLAG_DYNAMIC;
|
||||
return (ret);
|
||||
}
|
||||
|
||||
void ASN1_OBJECT_free(ASN1_OBJECT *a)
|
||||
{
|
||||
if (a == NULL)
|
||||
return;
|
||||
if (a->flags & ASN1_OBJECT_FLAG_DYNAMIC_STRINGS) {
|
||||
#ifndef CONST_STRICT /* disable purely for compile-time strict
|
||||
* const checking. Doing this on a "real"
|
||||
* compile will cause memory leaks */
|
||||
if (a->sn != NULL)
|
||||
OPENSSL_free((void *)a->sn);
|
||||
if (a->ln != NULL)
|
||||
OPENSSL_free((void *)a->ln);
|
||||
#endif
|
||||
a->sn = a->ln = NULL;
|
||||
}
|
||||
if (a->flags & ASN1_OBJECT_FLAG_DYNAMIC_DATA) {
|
||||
if (a->data != NULL)
|
||||
OPENSSL_free((void *)a->data);
|
||||
a->data = NULL;
|
||||
a->length = 0;
|
||||
}
|
||||
if (a->flags & ASN1_OBJECT_FLAG_DYNAMIC)
|
||||
OPENSSL_free(a);
|
||||
}
|
||||
|
||||
ASN1_OBJECT *ASN1_OBJECT_create(int nid, unsigned char *data, int len,
|
||||
const char *sn, const char *ln)
|
||||
{
|
||||
ASN1_OBJECT o;
|
||||
|
||||
o.sn = sn;
|
||||
o.ln = ln;
|
||||
o.data = data;
|
||||
o.nid = nid;
|
||||
o.length = len;
|
||||
o.flags = ASN1_OBJECT_FLAG_DYNAMIC | ASN1_OBJECT_FLAG_DYNAMIC_STRINGS |
|
||||
ASN1_OBJECT_FLAG_DYNAMIC_DATA;
|
||||
return (OBJ_dup(&o));
|
||||
}
|
||||
+77
@@ -0,0 +1,77 @@
|
||||
/* Copyright (C) 1995-1998 Eric Young ([email protected])
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young ([email protected]).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson ([email protected]).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young ([email protected])"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson ([email protected])"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.] */
|
||||
|
||||
#include <openssl_grpc/asn1.h>
|
||||
|
||||
#include <openssl_grpc/err.h>
|
||||
#include <openssl_grpc/mem.h>
|
||||
|
||||
ASN1_OCTET_STRING *ASN1_OCTET_STRING_dup(const ASN1_OCTET_STRING *x)
|
||||
{
|
||||
return M_ASN1_OCTET_STRING_dup(x);
|
||||
}
|
||||
|
||||
int ASN1_OCTET_STRING_cmp(const ASN1_OCTET_STRING *a,
|
||||
const ASN1_OCTET_STRING *b)
|
||||
{
|
||||
return M_ASN1_OCTET_STRING_cmp(a, b);
|
||||
}
|
||||
|
||||
int ASN1_OCTET_STRING_set(ASN1_OCTET_STRING *x, const unsigned char *d,
|
||||
int len)
|
||||
{
|
||||
return M_ASN1_OCTET_STRING_set(x, d, len);
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
/* Copyright (C) 1995-1998 Eric Young ([email protected])
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young ([email protected]).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson ([email protected]).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young ([email protected])"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson ([email protected])"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.] */
|
||||
|
||||
#include <openssl/asn1.h>
|
||||
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/mem.h>
|
||||
|
||||
ASN1_OCTET_STRING *ASN1_OCTET_STRING_dup(const ASN1_OCTET_STRING *x)
|
||||
{
|
||||
return M_ASN1_OCTET_STRING_dup(x);
|
||||
}
|
||||
|
||||
int ASN1_OCTET_STRING_cmp(const ASN1_OCTET_STRING *a,
|
||||
const ASN1_OCTET_STRING *b)
|
||||
{
|
||||
return M_ASN1_OCTET_STRING_cmp(a, b);
|
||||
}
|
||||
|
||||
int ASN1_OCTET_STRING_set(ASN1_OCTET_STRING *x, const unsigned char *d,
|
||||
int len)
|
||||
{
|
||||
return M_ASN1_OCTET_STRING_set(x, d, len);
|
||||
}
|
||||
+93
@@ -0,0 +1,93 @@
|
||||
/* Copyright (C) 1995-1998 Eric Young ([email protected])
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young ([email protected]).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson ([email protected]).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young ([email protected])"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson ([email protected])"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.] */
|
||||
|
||||
#include <openssl_grpc/asn1.h>
|
||||
|
||||
#include <openssl_grpc/err.h>
|
||||
#include <openssl_grpc/mem.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 (!(((c >= 'a') && (c <= 'z')) ||
|
||||
((c >= 'A') && (c <= 'Z')) ||
|
||||
(c == ' ') ||
|
||||
((c >= '0') && (c <= '9')) ||
|
||||
(c == ' ') || (c == '\'') ||
|
||||
(c == '(') || (c == ')') ||
|
||||
(c == '+') || (c == ',') ||
|
||||
(c == '-') || (c == '.') ||
|
||||
(c == '/') || (c == ':') || (c == '=') || (c == '?')))
|
||||
ia5 = 1;
|
||||
if (c & 0x80)
|
||||
t61 = 1;
|
||||
}
|
||||
if (t61)
|
||||
return (V_ASN1_T61STRING);
|
||||
if (ia5)
|
||||
return (V_ASN1_IA5STRING);
|
||||
return (V_ASN1_PRINTABLESTRING);
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
/* Copyright (C) 1995-1998 Eric Young ([email protected])
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young ([email protected]).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson ([email protected]).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young ([email protected])"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson ([email protected])"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.] */
|
||||
|
||||
#include <openssl/asn1.h>
|
||||
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/mem.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 (!(((c >= 'a') && (c <= 'z')) ||
|
||||
((c >= 'A') && (c <= 'Z')) ||
|
||||
(c == ' ') ||
|
||||
((c >= '0') && (c <= '9')) ||
|
||||
(c == ' ') || (c == '\'') ||
|
||||
(c == '(') || (c == ')') ||
|
||||
(c == '+') || (c == ',') ||
|
||||
(c == '-') || (c == '.') ||
|
||||
(c == '/') || (c == ':') || (c == '=') || (c == '?')))
|
||||
ia5 = 1;
|
||||
if (c & 0x80)
|
||||
t61 = 1;
|
||||
}
|
||||
if (t61)
|
||||
return (V_ASN1_T61STRING);
|
||||
if (ia5)
|
||||
return (V_ASN1_IA5STRING);
|
||||
return (V_ASN1_PRINTABLESTRING);
|
||||
}
|
||||
+313
@@ -0,0 +1,313 @@
|
||||
/* Copyright (C) 1995-1998 Eric Young ([email protected])
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young ([email protected]).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson ([email protected]).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young ([email protected])"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson ([email protected])"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.] */
|
||||
|
||||
#include <openssl_grpc/asn1.h>
|
||||
|
||||
#include <stdlib.h> /* For bsearch */
|
||||
#include <string.h>
|
||||
|
||||
#include <openssl_grpc/err.h>
|
||||
#include <openssl_grpc/mem.h>
|
||||
#include <openssl_grpc/obj.h>
|
||||
#include <openssl_grpc/stack.h>
|
||||
|
||||
DEFINE_STACK_OF(ASN1_STRING_TABLE)
|
||||
|
||||
static STACK_OF(ASN1_STRING_TABLE) *stable = NULL;
|
||||
static void st_free(ASN1_STRING_TABLE *tbl);
|
||||
|
||||
/*
|
||||
* This is the global mask for the mbstring functions: this is use to mask
|
||||
* out certain types (such as BMPString and UTF8String) because certain
|
||||
* software (e.g. Netscape) has problems with them.
|
||||
*/
|
||||
|
||||
static unsigned long global_mask = B_ASN1_UTF8STRING;
|
||||
|
||||
void ASN1_STRING_set_default_mask(unsigned long mask)
|
||||
{
|
||||
global_mask = mask;
|
||||
}
|
||||
|
||||
unsigned long ASN1_STRING_get_default_mask(void)
|
||||
{
|
||||
return global_mask;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function sets the default to various "flavours" of configuration.
|
||||
* based on an ASCII string. Currently this is: MASK:XXXX : a numerical mask
|
||||
* value. nobmp : Don't use BMPStrings (just Printable, T61). pkix : PKIX
|
||||
* recommendation in RFC2459. utf8only : only use UTF8Strings (RFC2459
|
||||
* recommendation for 2004). default: the default value, Printable, T61, BMP.
|
||||
*/
|
||||
|
||||
int ASN1_STRING_set_default_mask_asc(const char *p)
|
||||
{
|
||||
unsigned long mask;
|
||||
char *end;
|
||||
if (!strncmp(p, "MASK:", 5)) {
|
||||
if (!p[5])
|
||||
return 0;
|
||||
mask = strtoul(p + 5, &end, 0);
|
||||
if (*end)
|
||||
return 0;
|
||||
} else if (!strcmp(p, "nombstr"))
|
||||
mask = ~((unsigned long)(B_ASN1_BMPSTRING | B_ASN1_UTF8STRING));
|
||||
else if (!strcmp(p, "pkix"))
|
||||
mask = ~((unsigned long)B_ASN1_T61STRING);
|
||||
else if (!strcmp(p, "utf8only"))
|
||||
mask = B_ASN1_UTF8STRING;
|
||||
else if (!strcmp(p, "default"))
|
||||
mask = 0xFFFFFFFFL;
|
||||
else
|
||||
return 0;
|
||||
ASN1_STRING_set_default_mask(mask);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* The following function generates an ASN1_STRING based on limits in a
|
||||
* table. Frequently the types and length of an ASN1_STRING are restricted by
|
||||
* a corresponding OID. For example certificates and certificate requests.
|
||||
*/
|
||||
|
||||
ASN1_STRING *ASN1_STRING_set_by_NID(ASN1_STRING **out,
|
||||
const unsigned char *in, int inlen,
|
||||
int inform, int nid)
|
||||
{
|
||||
ASN1_STRING_TABLE *tbl;
|
||||
ASN1_STRING *str = NULL;
|
||||
unsigned long mask;
|
||||
int ret;
|
||||
if (!out)
|
||||
out = &str;
|
||||
tbl = ASN1_STRING_TABLE_get(nid);
|
||||
if (tbl) {
|
||||
mask = tbl->mask;
|
||||
if (!(tbl->flags & STABLE_NO_MASK))
|
||||
mask &= global_mask;
|
||||
ret = ASN1_mbstring_ncopy(out, in, inlen, inform, mask,
|
||||
tbl->minsize, tbl->maxsize);
|
||||
} else
|
||||
ret =
|
||||
ASN1_mbstring_copy(out, in, inlen, inform,
|
||||
DIRSTRING_TYPE & global_mask);
|
||||
if (ret <= 0)
|
||||
return NULL;
|
||||
return *out;
|
||||
}
|
||||
|
||||
/*
|
||||
* Now the tables and helper functions for the string table:
|
||||
*/
|
||||
|
||||
/* size limits: this stuff is taken straight from RFC3280 */
|
||||
|
||||
#define ub_name 32768
|
||||
#define ub_common_name 64
|
||||
#define ub_locality_name 128
|
||||
#define ub_state_name 128
|
||||
#define ub_organization_name 64
|
||||
#define ub_organization_unit_name 64
|
||||
#define ub_title 64
|
||||
#define ub_email_address 128
|
||||
#define ub_serial_number 64
|
||||
|
||||
/* This table must be kept in NID order */
|
||||
|
||||
static const ASN1_STRING_TABLE tbl_standard[] = {
|
||||
{NID_commonName, 1, ub_common_name, DIRSTRING_TYPE, 0},
|
||||
{NID_countryName, 2, 2, B_ASN1_PRINTABLESTRING, STABLE_NO_MASK},
|
||||
{NID_localityName, 1, ub_locality_name, DIRSTRING_TYPE, 0},
|
||||
{NID_stateOrProvinceName, 1, ub_state_name, DIRSTRING_TYPE, 0},
|
||||
{NID_organizationName, 1, ub_organization_name, DIRSTRING_TYPE, 0},
|
||||
{NID_organizationalUnitName, 1, ub_organization_unit_name, DIRSTRING_TYPE,
|
||||
0},
|
||||
{NID_pkcs9_emailAddress, 1, ub_email_address, B_ASN1_IA5STRING,
|
||||
STABLE_NO_MASK},
|
||||
{NID_pkcs9_unstructuredName, 1, -1, PKCS9STRING_TYPE, 0},
|
||||
{NID_pkcs9_challengePassword, 1, -1, PKCS9STRING_TYPE, 0},
|
||||
{NID_pkcs9_unstructuredAddress, 1, -1, DIRSTRING_TYPE, 0},
|
||||
{NID_givenName, 1, ub_name, DIRSTRING_TYPE, 0},
|
||||
{NID_surname, 1, ub_name, DIRSTRING_TYPE, 0},
|
||||
{NID_initials, 1, ub_name, DIRSTRING_TYPE, 0},
|
||||
{NID_serialNumber, 1, ub_serial_number, B_ASN1_PRINTABLESTRING,
|
||||
STABLE_NO_MASK},
|
||||
{NID_friendlyName, -1, -1, B_ASN1_BMPSTRING, STABLE_NO_MASK},
|
||||
{NID_name, 1, ub_name, DIRSTRING_TYPE, 0},
|
||||
{NID_dnQualifier, -1, -1, B_ASN1_PRINTABLESTRING, STABLE_NO_MASK},
|
||||
{NID_domainComponent, 1, -1, B_ASN1_IA5STRING, STABLE_NO_MASK},
|
||||
{NID_ms_csp_name, -1, -1, B_ASN1_BMPSTRING, STABLE_NO_MASK}
|
||||
};
|
||||
|
||||
static int sk_table_cmp(const ASN1_STRING_TABLE **a,
|
||||
const ASN1_STRING_TABLE **b)
|
||||
{
|
||||
return (*a)->nid - (*b)->nid;
|
||||
}
|
||||
|
||||
static int table_cmp(const void *in_a, const void *in_b)
|
||||
{
|
||||
const ASN1_STRING_TABLE *a = in_a;
|
||||
const ASN1_STRING_TABLE *b = in_b;
|
||||
return a->nid - b->nid;
|
||||
}
|
||||
|
||||
ASN1_STRING_TABLE *ASN1_STRING_TABLE_get(int nid)
|
||||
{
|
||||
int found;
|
||||
size_t idx;
|
||||
ASN1_STRING_TABLE *ttmp;
|
||||
ASN1_STRING_TABLE fnd;
|
||||
fnd.nid = nid;
|
||||
|
||||
ttmp =
|
||||
bsearch(&fnd, tbl_standard,
|
||||
sizeof(tbl_standard) / sizeof(ASN1_STRING_TABLE),
|
||||
sizeof(ASN1_STRING_TABLE), table_cmp);
|
||||
if (ttmp)
|
||||
return ttmp;
|
||||
if (!stable)
|
||||
return NULL;
|
||||
sk_ASN1_STRING_TABLE_sort(stable);
|
||||
found = sk_ASN1_STRING_TABLE_find(stable, &idx, &fnd);
|
||||
if (!found)
|
||||
return NULL;
|
||||
return sk_ASN1_STRING_TABLE_value(stable, idx);
|
||||
}
|
||||
|
||||
int ASN1_STRING_TABLE_add(int nid,
|
||||
long minsize, long maxsize, unsigned long mask,
|
||||
unsigned long flags)
|
||||
{
|
||||
ASN1_STRING_TABLE *tmp;
|
||||
char new_nid = 0;
|
||||
flags &= ~STABLE_FLAGS_MALLOC;
|
||||
if (!stable)
|
||||
stable = sk_ASN1_STRING_TABLE_new(sk_table_cmp);
|
||||
if (!stable) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
if (!(tmp = ASN1_STRING_TABLE_get(nid))) {
|
||||
tmp = OPENSSL_malloc(sizeof(ASN1_STRING_TABLE));
|
||||
if (!tmp) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
tmp->flags = flags | STABLE_FLAGS_MALLOC;
|
||||
tmp->nid = nid;
|
||||
tmp->minsize = tmp->maxsize = -1;
|
||||
new_nid = 1;
|
||||
} else
|
||||
tmp->flags = (tmp->flags & STABLE_FLAGS_MALLOC) | flags;
|
||||
if (minsize != -1)
|
||||
tmp->minsize = minsize;
|
||||
if (maxsize != -1)
|
||||
tmp->maxsize = maxsize;
|
||||
tmp->mask = mask;
|
||||
if (new_nid)
|
||||
sk_ASN1_STRING_TABLE_push(stable, tmp);
|
||||
return 1;
|
||||
}
|
||||
|
||||
void ASN1_STRING_TABLE_cleanup(void)
|
||||
{
|
||||
STACK_OF(ASN1_STRING_TABLE) *tmp;
|
||||
tmp = stable;
|
||||
if (!tmp)
|
||||
return;
|
||||
stable = NULL;
|
||||
sk_ASN1_STRING_TABLE_pop_free(tmp, st_free);
|
||||
}
|
||||
|
||||
static void st_free(ASN1_STRING_TABLE *tbl)
|
||||
{
|
||||
if (tbl->flags & STABLE_FLAGS_MALLOC)
|
||||
OPENSSL_free(tbl);
|
||||
}
|
||||
|
||||
#ifdef STRING_TABLE_TEST
|
||||
|
||||
int main(void)
|
||||
{
|
||||
ASN1_STRING_TABLE *tmp;
|
||||
int i, last_nid = -1;
|
||||
|
||||
for (tmp = tbl_standard, i = 0;
|
||||
i < sizeof(tbl_standard) / sizeof(ASN1_STRING_TABLE); i++, tmp++) {
|
||||
if (tmp->nid < last_nid) {
|
||||
last_nid = 0;
|
||||
break;
|
||||
}
|
||||
last_nid = tmp->nid;
|
||||
}
|
||||
|
||||
if (last_nid != 0) {
|
||||
printf("Table order OK\n");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
for (tmp = tbl_standard, i = 0;
|
||||
i < sizeof(tbl_standard) / sizeof(ASN1_STRING_TABLE); i++, tmp++)
|
||||
printf("Index %d, NID %d, Name=%s\n", i, tmp->nid,
|
||||
OBJ_nid2ln(tmp->nid));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,313 @@
|
||||
/* Copyright (C) 1995-1998 Eric Young ([email protected])
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young ([email protected]).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson ([email protected]).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young ([email protected])"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson ([email protected])"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.] */
|
||||
|
||||
#include <openssl/asn1.h>
|
||||
|
||||
#include <stdlib.h> /* For bsearch */
|
||||
#include <string.h>
|
||||
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/mem.h>
|
||||
#include <openssl/obj.h>
|
||||
#include <openssl/stack.h>
|
||||
|
||||
DEFINE_STACK_OF(ASN1_STRING_TABLE)
|
||||
|
||||
static STACK_OF(ASN1_STRING_TABLE) *stable = NULL;
|
||||
static void st_free(ASN1_STRING_TABLE *tbl);
|
||||
|
||||
/*
|
||||
* This is the global mask for the mbstring functions: this is use to mask
|
||||
* out certain types (such as BMPString and UTF8String) because certain
|
||||
* software (e.g. Netscape) has problems with them.
|
||||
*/
|
||||
|
||||
static unsigned long global_mask = B_ASN1_UTF8STRING;
|
||||
|
||||
void ASN1_STRING_set_default_mask(unsigned long mask)
|
||||
{
|
||||
global_mask = mask;
|
||||
}
|
||||
|
||||
unsigned long ASN1_STRING_get_default_mask(void)
|
||||
{
|
||||
return global_mask;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function sets the default to various "flavours" of configuration.
|
||||
* based on an ASCII string. Currently this is: MASK:XXXX : a numerical mask
|
||||
* value. nobmp : Don't use BMPStrings (just Printable, T61). pkix : PKIX
|
||||
* recommendation in RFC2459. utf8only : only use UTF8Strings (RFC2459
|
||||
* recommendation for 2004). default: the default value, Printable, T61, BMP.
|
||||
*/
|
||||
|
||||
int ASN1_STRING_set_default_mask_asc(const char *p)
|
||||
{
|
||||
unsigned long mask;
|
||||
char *end;
|
||||
if (!strncmp(p, "MASK:", 5)) {
|
||||
if (!p[5])
|
||||
return 0;
|
||||
mask = strtoul(p + 5, &end, 0);
|
||||
if (*end)
|
||||
return 0;
|
||||
} else if (!strcmp(p, "nombstr"))
|
||||
mask = ~((unsigned long)(B_ASN1_BMPSTRING | B_ASN1_UTF8STRING));
|
||||
else if (!strcmp(p, "pkix"))
|
||||
mask = ~((unsigned long)B_ASN1_T61STRING);
|
||||
else if (!strcmp(p, "utf8only"))
|
||||
mask = B_ASN1_UTF8STRING;
|
||||
else if (!strcmp(p, "default"))
|
||||
mask = 0xFFFFFFFFL;
|
||||
else
|
||||
return 0;
|
||||
ASN1_STRING_set_default_mask(mask);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* The following function generates an ASN1_STRING based on limits in a
|
||||
* table. Frequently the types and length of an ASN1_STRING are restricted by
|
||||
* a corresponding OID. For example certificates and certificate requests.
|
||||
*/
|
||||
|
||||
ASN1_STRING *ASN1_STRING_set_by_NID(ASN1_STRING **out,
|
||||
const unsigned char *in, int inlen,
|
||||
int inform, int nid)
|
||||
{
|
||||
ASN1_STRING_TABLE *tbl;
|
||||
ASN1_STRING *str = NULL;
|
||||
unsigned long mask;
|
||||
int ret;
|
||||
if (!out)
|
||||
out = &str;
|
||||
tbl = ASN1_STRING_TABLE_get(nid);
|
||||
if (tbl) {
|
||||
mask = tbl->mask;
|
||||
if (!(tbl->flags & STABLE_NO_MASK))
|
||||
mask &= global_mask;
|
||||
ret = ASN1_mbstring_ncopy(out, in, inlen, inform, mask,
|
||||
tbl->minsize, tbl->maxsize);
|
||||
} else
|
||||
ret =
|
||||
ASN1_mbstring_copy(out, in, inlen, inform,
|
||||
DIRSTRING_TYPE & global_mask);
|
||||
if (ret <= 0)
|
||||
return NULL;
|
||||
return *out;
|
||||
}
|
||||
|
||||
/*
|
||||
* Now the tables and helper functions for the string table:
|
||||
*/
|
||||
|
||||
/* size limits: this stuff is taken straight from RFC3280 */
|
||||
|
||||
#define ub_name 32768
|
||||
#define ub_common_name 64
|
||||
#define ub_locality_name 128
|
||||
#define ub_state_name 128
|
||||
#define ub_organization_name 64
|
||||
#define ub_organization_unit_name 64
|
||||
#define ub_title 64
|
||||
#define ub_email_address 128
|
||||
#define ub_serial_number 64
|
||||
|
||||
/* This table must be kept in NID order */
|
||||
|
||||
static const ASN1_STRING_TABLE tbl_standard[] = {
|
||||
{NID_commonName, 1, ub_common_name, DIRSTRING_TYPE, 0},
|
||||
{NID_countryName, 2, 2, B_ASN1_PRINTABLESTRING, STABLE_NO_MASK},
|
||||
{NID_localityName, 1, ub_locality_name, DIRSTRING_TYPE, 0},
|
||||
{NID_stateOrProvinceName, 1, ub_state_name, DIRSTRING_TYPE, 0},
|
||||
{NID_organizationName, 1, ub_organization_name, DIRSTRING_TYPE, 0},
|
||||
{NID_organizationalUnitName, 1, ub_organization_unit_name, DIRSTRING_TYPE,
|
||||
0},
|
||||
{NID_pkcs9_emailAddress, 1, ub_email_address, B_ASN1_IA5STRING,
|
||||
STABLE_NO_MASK},
|
||||
{NID_pkcs9_unstructuredName, 1, -1, PKCS9STRING_TYPE, 0},
|
||||
{NID_pkcs9_challengePassword, 1, -1, PKCS9STRING_TYPE, 0},
|
||||
{NID_pkcs9_unstructuredAddress, 1, -1, DIRSTRING_TYPE, 0},
|
||||
{NID_givenName, 1, ub_name, DIRSTRING_TYPE, 0},
|
||||
{NID_surname, 1, ub_name, DIRSTRING_TYPE, 0},
|
||||
{NID_initials, 1, ub_name, DIRSTRING_TYPE, 0},
|
||||
{NID_serialNumber, 1, ub_serial_number, B_ASN1_PRINTABLESTRING,
|
||||
STABLE_NO_MASK},
|
||||
{NID_friendlyName, -1, -1, B_ASN1_BMPSTRING, STABLE_NO_MASK},
|
||||
{NID_name, 1, ub_name, DIRSTRING_TYPE, 0},
|
||||
{NID_dnQualifier, -1, -1, B_ASN1_PRINTABLESTRING, STABLE_NO_MASK},
|
||||
{NID_domainComponent, 1, -1, B_ASN1_IA5STRING, STABLE_NO_MASK},
|
||||
{NID_ms_csp_name, -1, -1, B_ASN1_BMPSTRING, STABLE_NO_MASK}
|
||||
};
|
||||
|
||||
static int sk_table_cmp(const ASN1_STRING_TABLE **a,
|
||||
const ASN1_STRING_TABLE **b)
|
||||
{
|
||||
return (*a)->nid - (*b)->nid;
|
||||
}
|
||||
|
||||
static int table_cmp(const void *in_a, const void *in_b)
|
||||
{
|
||||
const ASN1_STRING_TABLE *a = in_a;
|
||||
const ASN1_STRING_TABLE *b = in_b;
|
||||
return a->nid - b->nid;
|
||||
}
|
||||
|
||||
ASN1_STRING_TABLE *ASN1_STRING_TABLE_get(int nid)
|
||||
{
|
||||
int found;
|
||||
size_t idx;
|
||||
ASN1_STRING_TABLE *ttmp;
|
||||
ASN1_STRING_TABLE fnd;
|
||||
fnd.nid = nid;
|
||||
|
||||
ttmp =
|
||||
bsearch(&fnd, tbl_standard,
|
||||
sizeof(tbl_standard) / sizeof(ASN1_STRING_TABLE),
|
||||
sizeof(ASN1_STRING_TABLE), table_cmp);
|
||||
if (ttmp)
|
||||
return ttmp;
|
||||
if (!stable)
|
||||
return NULL;
|
||||
sk_ASN1_STRING_TABLE_sort(stable);
|
||||
found = sk_ASN1_STRING_TABLE_find(stable, &idx, &fnd);
|
||||
if (!found)
|
||||
return NULL;
|
||||
return sk_ASN1_STRING_TABLE_value(stable, idx);
|
||||
}
|
||||
|
||||
int ASN1_STRING_TABLE_add(int nid,
|
||||
long minsize, long maxsize, unsigned long mask,
|
||||
unsigned long flags)
|
||||
{
|
||||
ASN1_STRING_TABLE *tmp;
|
||||
char new_nid = 0;
|
||||
flags &= ~STABLE_FLAGS_MALLOC;
|
||||
if (!stable)
|
||||
stable = sk_ASN1_STRING_TABLE_new(sk_table_cmp);
|
||||
if (!stable) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
if (!(tmp = ASN1_STRING_TABLE_get(nid))) {
|
||||
tmp = OPENSSL_malloc(sizeof(ASN1_STRING_TABLE));
|
||||
if (!tmp) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
tmp->flags = flags | STABLE_FLAGS_MALLOC;
|
||||
tmp->nid = nid;
|
||||
tmp->minsize = tmp->maxsize = -1;
|
||||
new_nid = 1;
|
||||
} else
|
||||
tmp->flags = (tmp->flags & STABLE_FLAGS_MALLOC) | flags;
|
||||
if (minsize != -1)
|
||||
tmp->minsize = minsize;
|
||||
if (maxsize != -1)
|
||||
tmp->maxsize = maxsize;
|
||||
tmp->mask = mask;
|
||||
if (new_nid)
|
||||
sk_ASN1_STRING_TABLE_push(stable, tmp);
|
||||
return 1;
|
||||
}
|
||||
|
||||
void ASN1_STRING_TABLE_cleanup(void)
|
||||
{
|
||||
STACK_OF(ASN1_STRING_TABLE) *tmp;
|
||||
tmp = stable;
|
||||
if (!tmp)
|
||||
return;
|
||||
stable = NULL;
|
||||
sk_ASN1_STRING_TABLE_pop_free(tmp, st_free);
|
||||
}
|
||||
|
||||
static void st_free(ASN1_STRING_TABLE *tbl)
|
||||
{
|
||||
if (tbl->flags & STABLE_FLAGS_MALLOC)
|
||||
OPENSSL_free(tbl);
|
||||
}
|
||||
|
||||
#ifdef STRING_TABLE_TEST
|
||||
|
||||
int main(void)
|
||||
{
|
||||
ASN1_STRING_TABLE *tmp;
|
||||
int i, last_nid = -1;
|
||||
|
||||
for (tmp = tbl_standard, i = 0;
|
||||
i < sizeof(tbl_standard) / sizeof(ASN1_STRING_TABLE); i++, tmp++) {
|
||||
if (tmp->nid < last_nid) {
|
||||
last_nid = 0;
|
||||
break;
|
||||
}
|
||||
last_nid = tmp->nid;
|
||||
}
|
||||
|
||||
if (last_nid != 0) {
|
||||
printf("Table order OK\n");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
for (tmp = tbl_standard, i = 0;
|
||||
i < sizeof(tbl_standard) / sizeof(ASN1_STRING_TABLE); i++, tmp++)
|
||||
printf("Index %d, NID %d, Name=%s\n", i, tmp->nid,
|
||||
OBJ_nid2ln(tmp->nid));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
+212
@@ -0,0 +1,212 @@
|
||||
/* Copyright (C) 1995-1998 Eric Young ([email protected])
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young ([email protected]).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson ([email protected]).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young ([email protected])"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson ([email protected])"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.] */
|
||||
|
||||
#include <openssl_grpc/asn1.h>
|
||||
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
#include <openssl_grpc/asn1t.h>
|
||||
#include <openssl_grpc/err.h>
|
||||
#include <openssl_grpc/mem.h>
|
||||
|
||||
#include "asn1_locl.h"
|
||||
|
||||
/*
|
||||
* This is an implementation of the ASN1 Time structure which is: Time ::=
|
||||
* CHOICE { utcTime UTCTime, generalTime GeneralizedTime } written by Steve
|
||||
* Henson.
|
||||
*/
|
||||
|
||||
IMPLEMENT_ASN1_MSTRING(ASN1_TIME, B_ASN1_TIME)
|
||||
|
||||
IMPLEMENT_ASN1_FUNCTIONS(ASN1_TIME)
|
||||
|
||||
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) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_ERROR_GETTING_TIME);
|
||||
return NULL;
|
||||
}
|
||||
if (offset_day || offset_sec) {
|
||||
if (!OPENSSL_gmtime_adj(ts, offset_day, offset_sec))
|
||||
return NULL;
|
||||
}
|
||||
if ((ts->tm_year >= 50) && (ts->tm_year < 150))
|
||||
return ASN1_UTCTIME_adj(s, t, offset_day, offset_sec);
|
||||
return ASN1_GENERALIZEDTIME_adj(s, t, offset_day, offset_sec);
|
||||
}
|
||||
|
||||
int ASN1_TIME_check(ASN1_TIME *t)
|
||||
{
|
||||
if (t->type == V_ASN1_GENERALIZEDTIME)
|
||||
return ASN1_GENERALIZEDTIME_check(t);
|
||||
else if (t->type == V_ASN1_UTCTIME)
|
||||
return ASN1_UTCTIME_check(t);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Convert an ASN1_TIME structure to GeneralizedTime */
|
||||
ASN1_GENERALIZEDTIME *ASN1_TIME_to_generalizedtime(ASN1_TIME *t,
|
||||
ASN1_GENERALIZEDTIME **out)
|
||||
{
|
||||
ASN1_GENERALIZEDTIME *ret = NULL;
|
||||
char *str;
|
||||
int newlen;
|
||||
|
||||
if (!ASN1_TIME_check(t))
|
||||
return NULL;
|
||||
|
||||
if (!out || !*out) {
|
||||
if (!(ret = ASN1_GENERALIZEDTIME_new()))
|
||||
goto err;
|
||||
} else {
|
||||
ret = *out;
|
||||
}
|
||||
|
||||
/* If already GeneralizedTime just copy across */
|
||||
if (t->type == V_ASN1_GENERALIZEDTIME) {
|
||||
if (!ASN1_STRING_set(ret, t->data, t->length))
|
||||
goto err;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* grow the string */
|
||||
if (!ASN1_STRING_set(ret, NULL, t->length + 2))
|
||||
goto err;
|
||||
/* ASN1_STRING_set() allocated 'len + 1' bytes. */
|
||||
newlen = t->length + 2 + 1;
|
||||
str = (char *)ret->data;
|
||||
/* Work out the century and prepend */
|
||||
if (t->data[0] >= '5')
|
||||
OPENSSL_strlcpy(str, "19", newlen);
|
||||
else
|
||||
OPENSSL_strlcpy(str, "20", newlen);
|
||||
|
||||
OPENSSL_strlcat(str, (char *)t->data, newlen);
|
||||
|
||||
done:
|
||||
if (out != NULL && *out == NULL)
|
||||
*out = ret;
|
||||
return ret;
|
||||
|
||||
err:
|
||||
if (out == NULL || *out != ret)
|
||||
ASN1_GENERALIZEDTIME_free(ret);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
int ASN1_TIME_set_string(ASN1_TIME *s, const char *str)
|
||||
{
|
||||
ASN1_TIME t;
|
||||
|
||||
t.length = strlen(str);
|
||||
t.data = (unsigned char *)str;
|
||||
t.flags = 0;
|
||||
|
||||
t.type = V_ASN1_UTCTIME;
|
||||
|
||||
if (!ASN1_TIME_check(&t)) {
|
||||
t.type = V_ASN1_GENERALIZEDTIME;
|
||||
if (!ASN1_TIME_check(&t))
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (s && !ASN1_STRING_copy((ASN1_STRING *)s, (ASN1_STRING *)&t))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int asn1_time_to_tm(struct tm *tm, const ASN1_TIME *t)
|
||||
{
|
||||
if (t == NULL) {
|
||||
time_t now_t;
|
||||
time(&now_t);
|
||||
if (OPENSSL_gmtime(&now_t, tm))
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (t->type == V_ASN1_UTCTIME)
|
||||
return asn1_utctime_to_tm(tm, t);
|
||||
else if (t->type == V_ASN1_GENERALIZEDTIME)
|
||||
return asn1_generalizedtime_to_tm(tm, t);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ASN1_TIME_diff(int *pday, int *psec,
|
||||
const ASN1_TIME *from, const ASN1_TIME *to)
|
||||
{
|
||||
struct tm tm_from, tm_to;
|
||||
if (!asn1_time_to_tm(&tm_from, from))
|
||||
return 0;
|
||||
if (!asn1_time_to_tm(&tm_to, to))
|
||||
return 0;
|
||||
return OPENSSL_gmtime_diff(pday, psec, &tm_from, &tm_to);
|
||||
}
|
||||
+212
@@ -0,0 +1,212 @@
|
||||
/* Copyright (C) 1995-1998 Eric Young ([email protected])
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young ([email protected]).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson ([email protected]).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young ([email protected])"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson ([email protected])"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.] */
|
||||
|
||||
#include <openssl/asn1.h>
|
||||
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
#include <openssl/asn1t.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/mem.h>
|
||||
|
||||
#include "asn1_locl.h"
|
||||
|
||||
/*
|
||||
* This is an implementation of the ASN1 Time structure which is: Time ::=
|
||||
* CHOICE { utcTime UTCTime, generalTime GeneralizedTime } written by Steve
|
||||
* Henson.
|
||||
*/
|
||||
|
||||
IMPLEMENT_ASN1_MSTRING(ASN1_TIME, B_ASN1_TIME)
|
||||
|
||||
IMPLEMENT_ASN1_FUNCTIONS(ASN1_TIME)
|
||||
|
||||
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) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_ERROR_GETTING_TIME);
|
||||
return NULL;
|
||||
}
|
||||
if (offset_day || offset_sec) {
|
||||
if (!OPENSSL_gmtime_adj(ts, offset_day, offset_sec))
|
||||
return NULL;
|
||||
}
|
||||
if ((ts->tm_year >= 50) && (ts->tm_year < 150))
|
||||
return ASN1_UTCTIME_adj(s, t, offset_day, offset_sec);
|
||||
return ASN1_GENERALIZEDTIME_adj(s, t, offset_day, offset_sec);
|
||||
}
|
||||
|
||||
int ASN1_TIME_check(ASN1_TIME *t)
|
||||
{
|
||||
if (t->type == V_ASN1_GENERALIZEDTIME)
|
||||
return ASN1_GENERALIZEDTIME_check(t);
|
||||
else if (t->type == V_ASN1_UTCTIME)
|
||||
return ASN1_UTCTIME_check(t);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Convert an ASN1_TIME structure to GeneralizedTime */
|
||||
ASN1_GENERALIZEDTIME *ASN1_TIME_to_generalizedtime(ASN1_TIME *t,
|
||||
ASN1_GENERALIZEDTIME **out)
|
||||
{
|
||||
ASN1_GENERALIZEDTIME *ret = NULL;
|
||||
char *str;
|
||||
int newlen;
|
||||
|
||||
if (!ASN1_TIME_check(t))
|
||||
return NULL;
|
||||
|
||||
if (!out || !*out) {
|
||||
if (!(ret = ASN1_GENERALIZEDTIME_new()))
|
||||
goto err;
|
||||
} else {
|
||||
ret = *out;
|
||||
}
|
||||
|
||||
/* If already GeneralizedTime just copy across */
|
||||
if (t->type == V_ASN1_GENERALIZEDTIME) {
|
||||
if (!ASN1_STRING_set(ret, t->data, t->length))
|
||||
goto err;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* grow the string */
|
||||
if (!ASN1_STRING_set(ret, NULL, t->length + 2))
|
||||
goto err;
|
||||
/* ASN1_STRING_set() allocated 'len + 1' bytes. */
|
||||
newlen = t->length + 2 + 1;
|
||||
str = (char *)ret->data;
|
||||
/* Work out the century and prepend */
|
||||
if (t->data[0] >= '5')
|
||||
OPENSSL_strlcpy(str, "19", newlen);
|
||||
else
|
||||
OPENSSL_strlcpy(str, "20", newlen);
|
||||
|
||||
OPENSSL_strlcat(str, (char *)t->data, newlen);
|
||||
|
||||
done:
|
||||
if (out != NULL && *out == NULL)
|
||||
*out = ret;
|
||||
return ret;
|
||||
|
||||
err:
|
||||
if (out == NULL || *out != ret)
|
||||
ASN1_GENERALIZEDTIME_free(ret);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
int ASN1_TIME_set_string(ASN1_TIME *s, const char *str)
|
||||
{
|
||||
ASN1_TIME t;
|
||||
|
||||
t.length = strlen(str);
|
||||
t.data = (unsigned char *)str;
|
||||
t.flags = 0;
|
||||
|
||||
t.type = V_ASN1_UTCTIME;
|
||||
|
||||
if (!ASN1_TIME_check(&t)) {
|
||||
t.type = V_ASN1_GENERALIZEDTIME;
|
||||
if (!ASN1_TIME_check(&t))
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (s && !ASN1_STRING_copy((ASN1_STRING *)s, (ASN1_STRING *)&t))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int asn1_time_to_tm(struct tm *tm, const ASN1_TIME *t)
|
||||
{
|
||||
if (t == NULL) {
|
||||
time_t now_t;
|
||||
time(&now_t);
|
||||
if (OPENSSL_gmtime(&now_t, tm))
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (t->type == V_ASN1_UTCTIME)
|
||||
return asn1_utctime_to_tm(tm, t);
|
||||
else if (t->type == V_ASN1_GENERALIZEDTIME)
|
||||
return asn1_generalizedtime_to_tm(tm, t);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ASN1_TIME_diff(int *pday, int *psec,
|
||||
const ASN1_TIME *from, const ASN1_TIME *to)
|
||||
{
|
||||
struct tm tm_from, tm_to;
|
||||
if (!asn1_time_to_tm(&tm_from, from))
|
||||
return 0;
|
||||
if (!asn1_time_to_tm(&tm_to, to))
|
||||
return 0;
|
||||
return OPENSSL_gmtime_diff(pday, psec, &tm_from, &tm_to);
|
||||
}
|
||||
+151
@@ -0,0 +1,151 @@
|
||||
/* Copyright (C) 1995-1998 Eric Young ([email protected])
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young ([email protected]).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson ([email protected]).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young ([email protected])"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson ([email protected])"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.] */
|
||||
|
||||
#include <openssl_grpc/asn1.h>
|
||||
|
||||
#include <openssl_grpc/asn1t.h>
|
||||
#include <openssl_grpc/err.h>
|
||||
#include <openssl_grpc/mem.h>
|
||||
#include <openssl_grpc/obj.h>
|
||||
|
||||
int ASN1_TYPE_get(ASN1_TYPE *a)
|
||||
{
|
||||
if ((a->value.ptr != NULL) || (a->type == V_ASN1_NULL))
|
||||
return (a->type);
|
||||
else
|
||||
return (0);
|
||||
}
|
||||
|
||||
void ASN1_TYPE_set(ASN1_TYPE *a, int type, void *value)
|
||||
{
|
||||
if (a->value.ptr != NULL) {
|
||||
ASN1_TYPE **tmp_a = &a;
|
||||
ASN1_primitive_free((ASN1_VALUE **)tmp_a, NULL);
|
||||
}
|
||||
a->type = type;
|
||||
if (type == V_ASN1_BOOLEAN)
|
||||
a->value.boolean = value ? 0xff : 0;
|
||||
else
|
||||
a->value.ptr = value;
|
||||
}
|
||||
|
||||
int ASN1_TYPE_set1(ASN1_TYPE *a, int type, const void *value)
|
||||
{
|
||||
if (!value || (type == V_ASN1_BOOLEAN)) {
|
||||
void *p = (void *)value;
|
||||
ASN1_TYPE_set(a, type, p);
|
||||
} else if (type == V_ASN1_OBJECT) {
|
||||
ASN1_OBJECT *odup;
|
||||
odup = OBJ_dup(value);
|
||||
if (!odup)
|
||||
return 0;
|
||||
ASN1_TYPE_set(a, type, odup);
|
||||
} else {
|
||||
ASN1_STRING *sdup;
|
||||
sdup = ASN1_STRING_dup(value);
|
||||
if (!sdup)
|
||||
return 0;
|
||||
ASN1_TYPE_set(a, type, sdup);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* 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_NULL:
|
||||
result = 0; /* They do not have content. */
|
||||
break;
|
||||
case V_ASN1_BOOLEAN:
|
||||
result = a->value.boolean - b->value.boolean;
|
||||
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;
|
||||
}
|
||||
+151
@@ -0,0 +1,151 @@
|
||||
/* Copyright (C) 1995-1998 Eric Young ([email protected])
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young ([email protected]).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson ([email protected]).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young ([email protected])"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson ([email protected])"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.] */
|
||||
|
||||
#include <openssl/asn1.h>
|
||||
|
||||
#include <openssl/asn1t.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/mem.h>
|
||||
#include <openssl/obj.h>
|
||||
|
||||
int ASN1_TYPE_get(ASN1_TYPE *a)
|
||||
{
|
||||
if ((a->value.ptr != NULL) || (a->type == V_ASN1_NULL))
|
||||
return (a->type);
|
||||
else
|
||||
return (0);
|
||||
}
|
||||
|
||||
void ASN1_TYPE_set(ASN1_TYPE *a, int type, void *value)
|
||||
{
|
||||
if (a->value.ptr != NULL) {
|
||||
ASN1_TYPE **tmp_a = &a;
|
||||
ASN1_primitive_free((ASN1_VALUE **)tmp_a, NULL);
|
||||
}
|
||||
a->type = type;
|
||||
if (type == V_ASN1_BOOLEAN)
|
||||
a->value.boolean = value ? 0xff : 0;
|
||||
else
|
||||
a->value.ptr = value;
|
||||
}
|
||||
|
||||
int ASN1_TYPE_set1(ASN1_TYPE *a, int type, const void *value)
|
||||
{
|
||||
if (!value || (type == V_ASN1_BOOLEAN)) {
|
||||
void *p = (void *)value;
|
||||
ASN1_TYPE_set(a, type, p);
|
||||
} else if (type == V_ASN1_OBJECT) {
|
||||
ASN1_OBJECT *odup;
|
||||
odup = OBJ_dup(value);
|
||||
if (!odup)
|
||||
return 0;
|
||||
ASN1_TYPE_set(a, type, odup);
|
||||
} else {
|
||||
ASN1_STRING *sdup;
|
||||
sdup = ASN1_STRING_dup(value);
|
||||
if (!sdup)
|
||||
return 0;
|
||||
ASN1_TYPE_set(a, type, sdup);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* 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_NULL:
|
||||
result = 0; /* They do not have content. */
|
||||
break;
|
||||
case V_ASN1_BOOLEAN:
|
||||
result = a->value.boolean - b->value.boolean;
|
||||
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;
|
||||
}
|
||||
+303
@@ -0,0 +1,303 @@
|
||||
/* Copyright (C) 1995-1998 Eric Young ([email protected])
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young ([email protected]).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson ([email protected]).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young ([email protected])"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson ([email protected])"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.] */
|
||||
|
||||
#include <openssl_grpc/asn1.h>
|
||||
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
#include <openssl_grpc/err.h>
|
||||
#include <openssl_grpc/mem.h>
|
||||
|
||||
#include "asn1_locl.h"
|
||||
|
||||
|
||||
int asn1_utctime_to_tm(struct tm *tm, const ASN1_UTCTIME *d)
|
||||
{
|
||||
static const int min[8] = { 0, 1, 1, 0, 0, 0, 0, 0 };
|
||||
static const int max[8] = { 99, 12, 31, 23, 59, 59, 12, 59 };
|
||||
char *a;
|
||||
int n, i, l, o;
|
||||
|
||||
if (d->type != V_ASN1_UTCTIME)
|
||||
return (0);
|
||||
l = d->length;
|
||||
a = (char *)d->data;
|
||||
o = 0;
|
||||
|
||||
if (l < 11)
|
||||
goto err;
|
||||
for (i = 0; i < 6; i++) {
|
||||
if ((i == 5) && ((a[o] == 'Z') || (a[o] == '+') || (a[o] == '-'))) {
|
||||
i++;
|
||||
if (tm)
|
||||
tm->tm_sec = 0;
|
||||
break;
|
||||
}
|
||||
if ((a[o] < '0') || (a[o] > '9'))
|
||||
goto err;
|
||||
n = a[o] - '0';
|
||||
if (++o > l)
|
||||
goto err;
|
||||
|
||||
if ((a[o] < '0') || (a[o] > '9'))
|
||||
goto err;
|
||||
n = (n * 10) + a[o] - '0';
|
||||
if (++o > l)
|
||||
goto err;
|
||||
|
||||
if ((n < min[i]) || (n > max[i]))
|
||||
goto err;
|
||||
if (tm) {
|
||||
switch (i) {
|
||||
case 0:
|
||||
tm->tm_year = n < 50 ? n + 100 : n;
|
||||
break;
|
||||
case 1:
|
||||
tm->tm_mon = n - 1;
|
||||
break;
|
||||
case 2:
|
||||
tm->tm_mday = n;
|
||||
break;
|
||||
case 3:
|
||||
tm->tm_hour = n;
|
||||
break;
|
||||
case 4:
|
||||
tm->tm_min = n;
|
||||
break;
|
||||
case 5:
|
||||
tm->tm_sec = n;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (a[o] == 'Z')
|
||||
o++;
|
||||
else if ((a[o] == '+') || (a[o] == '-')) {
|
||||
int offsign = a[o] == '-' ? 1 : -1, offset = 0;
|
||||
o++;
|
||||
if (o + 4 > l)
|
||||
goto err;
|
||||
for (i = 6; i < 8; i++) {
|
||||
if ((a[o] < '0') || (a[o] > '9'))
|
||||
goto err;
|
||||
n = a[o] - '0';
|
||||
o++;
|
||||
if ((a[o] < '0') || (a[o] > '9'))
|
||||
goto err;
|
||||
n = (n * 10) + a[o] - '0';
|
||||
if ((n < min[i]) || (n > max[i]))
|
||||
goto err;
|
||||
if (tm) {
|
||||
if (i == 6)
|
||||
offset = n * 3600;
|
||||
else if (i == 7)
|
||||
offset += n * 60;
|
||||
}
|
||||
o++;
|
||||
}
|
||||
if (offset && !OPENSSL_gmtime_adj(tm, 0, offset * offsign))
|
||||
return 0;
|
||||
}
|
||||
return o == l;
|
||||
err:
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ASN1_UTCTIME_check(const ASN1_UTCTIME *d)
|
||||
{
|
||||
return asn1_utctime_to_tm(NULL, d);
|
||||
}
|
||||
|
||||
int ASN1_UTCTIME_set_string(ASN1_UTCTIME *s, const char *str)
|
||||
{
|
||||
ASN1_UTCTIME t;
|
||||
|
||||
t.type = V_ASN1_UTCTIME;
|
||||
t.length = strlen(str);
|
||||
t.data = (unsigned char *)str;
|
||||
if (ASN1_UTCTIME_check(&t)) {
|
||||
if (s != NULL) {
|
||||
if (!ASN1_STRING_set((ASN1_STRING *)s,
|
||||
(unsigned char *)str, t.length))
|
||||
return 0;
|
||||
s->type = V_ASN1_UTCTIME;
|
||||
}
|
||||
return (1);
|
||||
} else
|
||||
return (0);
|
||||
}
|
||||
|
||||
ASN1_UTCTIME *ASN1_UTCTIME_set(ASN1_UTCTIME *s, time_t t)
|
||||
{
|
||||
return ASN1_UTCTIME_adj(s, t, 0, 0);
|
||||
}
|
||||
|
||||
ASN1_UTCTIME *ASN1_UTCTIME_adj(ASN1_UTCTIME *s, time_t t,
|
||||
int offset_day, long offset_sec)
|
||||
{
|
||||
char *p;
|
||||
struct tm *ts;
|
||||
struct tm data;
|
||||
size_t len = 20;
|
||||
int free_s = 0;
|
||||
|
||||
if (s == NULL) {
|
||||
free_s = 1;
|
||||
s = M_ASN1_UTCTIME_new();
|
||||
}
|
||||
if (s == NULL)
|
||||
goto err;
|
||||
|
||||
ts = OPENSSL_gmtime(&t, &data);
|
||||
if (ts == NULL)
|
||||
goto err;
|
||||
|
||||
if (offset_day || offset_sec) {
|
||||
if (!OPENSSL_gmtime_adj(ts, offset_day, offset_sec))
|
||||
goto err;
|
||||
}
|
||||
|
||||
if ((ts->tm_year < 50) || (ts->tm_year >= 150))
|
||||
goto err;
|
||||
|
||||
p = (char *)s->data;
|
||||
if ((p == NULL) || ((size_t)s->length < len)) {
|
||||
p = OPENSSL_malloc(len);
|
||||
if (p == NULL) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
if (s->data != NULL)
|
||||
OPENSSL_free(s->data);
|
||||
s->data = (unsigned char *)p;
|
||||
}
|
||||
|
||||
BIO_snprintf(p, len, "%02d%02d%02d%02d%02d%02dZ", ts->tm_year % 100,
|
||||
ts->tm_mon + 1, ts->tm_mday, ts->tm_hour, ts->tm_min,
|
||||
ts->tm_sec);
|
||||
s->length = strlen(p);
|
||||
s->type = V_ASN1_UTCTIME;
|
||||
return (s);
|
||||
err:
|
||||
if (free_s && s)
|
||||
M_ASN1_UTCTIME_free(s);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int ASN1_UTCTIME_cmp_time_t(const ASN1_UTCTIME *s, time_t t)
|
||||
{
|
||||
struct tm stm, ttm;
|
||||
int day, sec;
|
||||
|
||||
if (!asn1_utctime_to_tm(&stm, s))
|
||||
return -2;
|
||||
|
||||
if (!OPENSSL_gmtime(&t, &ttm))
|
||||
return -2;
|
||||
|
||||
if (!OPENSSL_gmtime_diff(&day, &sec, &ttm, &stm))
|
||||
return -2;
|
||||
|
||||
if (day > 0)
|
||||
return 1;
|
||||
if (day < 0)
|
||||
return -1;
|
||||
if (sec > 0)
|
||||
return 1;
|
||||
if (sec < 0)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if 0
|
||||
time_t ASN1_UTCTIME_get(const ASN1_UTCTIME *s)
|
||||
{
|
||||
struct tm tm;
|
||||
int offset;
|
||||
|
||||
OPENSSL_memset(&tm, '\0', sizeof tm);
|
||||
|
||||
# define g2(p) (((p)[0]-'0')*10+(p)[1]-'0')
|
||||
tm.tm_year = g2(s->data);
|
||||
if (tm.tm_year < 50)
|
||||
tm.tm_year += 100;
|
||||
tm.tm_mon = g2(s->data + 2) - 1;
|
||||
tm.tm_mday = g2(s->data + 4);
|
||||
tm.tm_hour = g2(s->data + 6);
|
||||
tm.tm_min = g2(s->data + 8);
|
||||
tm.tm_sec = g2(s->data + 10);
|
||||
if (s->data[12] == 'Z')
|
||||
offset = 0;
|
||||
else {
|
||||
offset = g2(s->data + 13) * 60 + g2(s->data + 15);
|
||||
if (s->data[12] == '-')
|
||||
offset = -offset;
|
||||
}
|
||||
# undef g2
|
||||
|
||||
return mktime(&tm) - offset * 60; /* FIXME: mktime assumes the current
|
||||
* timezone instead of UTC, and unless
|
||||
* we rewrite OpenSSL in Lisp we cannot
|
||||
* locally change the timezone without
|
||||
* possibly interfering with other
|
||||
* parts of the program. timegm, which
|
||||
* uses UTC, is non-standard. Also
|
||||
* time_t is inappropriate for general
|
||||
* UTC times because it may a 32 bit
|
||||
* type. */
|
||||
}
|
||||
#endif
|
||||
+303
@@ -0,0 +1,303 @@
|
||||
/* Copyright (C) 1995-1998 Eric Young ([email protected])
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young ([email protected]).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson ([email protected]).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young ([email protected])"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson ([email protected])"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.] */
|
||||
|
||||
#include <openssl/asn1.h>
|
||||
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/mem.h>
|
||||
|
||||
#include "asn1_locl.h"
|
||||
|
||||
|
||||
int asn1_utctime_to_tm(struct tm *tm, const ASN1_UTCTIME *d)
|
||||
{
|
||||
static const int min[8] = { 0, 1, 1, 0, 0, 0, 0, 0 };
|
||||
static const int max[8] = { 99, 12, 31, 23, 59, 59, 12, 59 };
|
||||
char *a;
|
||||
int n, i, l, o;
|
||||
|
||||
if (d->type != V_ASN1_UTCTIME)
|
||||
return (0);
|
||||
l = d->length;
|
||||
a = (char *)d->data;
|
||||
o = 0;
|
||||
|
||||
if (l < 11)
|
||||
goto err;
|
||||
for (i = 0; i < 6; i++) {
|
||||
if ((i == 5) && ((a[o] == 'Z') || (a[o] == '+') || (a[o] == '-'))) {
|
||||
i++;
|
||||
if (tm)
|
||||
tm->tm_sec = 0;
|
||||
break;
|
||||
}
|
||||
if ((a[o] < '0') || (a[o] > '9'))
|
||||
goto err;
|
||||
n = a[o] - '0';
|
||||
if (++o > l)
|
||||
goto err;
|
||||
|
||||
if ((a[o] < '0') || (a[o] > '9'))
|
||||
goto err;
|
||||
n = (n * 10) + a[o] - '0';
|
||||
if (++o > l)
|
||||
goto err;
|
||||
|
||||
if ((n < min[i]) || (n > max[i]))
|
||||
goto err;
|
||||
if (tm) {
|
||||
switch (i) {
|
||||
case 0:
|
||||
tm->tm_year = n < 50 ? n + 100 : n;
|
||||
break;
|
||||
case 1:
|
||||
tm->tm_mon = n - 1;
|
||||
break;
|
||||
case 2:
|
||||
tm->tm_mday = n;
|
||||
break;
|
||||
case 3:
|
||||
tm->tm_hour = n;
|
||||
break;
|
||||
case 4:
|
||||
tm->tm_min = n;
|
||||
break;
|
||||
case 5:
|
||||
tm->tm_sec = n;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (a[o] == 'Z')
|
||||
o++;
|
||||
else if ((a[o] == '+') || (a[o] == '-')) {
|
||||
int offsign = a[o] == '-' ? 1 : -1, offset = 0;
|
||||
o++;
|
||||
if (o + 4 > l)
|
||||
goto err;
|
||||
for (i = 6; i < 8; i++) {
|
||||
if ((a[o] < '0') || (a[o] > '9'))
|
||||
goto err;
|
||||
n = a[o] - '0';
|
||||
o++;
|
||||
if ((a[o] < '0') || (a[o] > '9'))
|
||||
goto err;
|
||||
n = (n * 10) + a[o] - '0';
|
||||
if ((n < min[i]) || (n > max[i]))
|
||||
goto err;
|
||||
if (tm) {
|
||||
if (i == 6)
|
||||
offset = n * 3600;
|
||||
else if (i == 7)
|
||||
offset += n * 60;
|
||||
}
|
||||
o++;
|
||||
}
|
||||
if (offset && !OPENSSL_gmtime_adj(tm, 0, offset * offsign))
|
||||
return 0;
|
||||
}
|
||||
return o == l;
|
||||
err:
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ASN1_UTCTIME_check(const ASN1_UTCTIME *d)
|
||||
{
|
||||
return asn1_utctime_to_tm(NULL, d);
|
||||
}
|
||||
|
||||
int ASN1_UTCTIME_set_string(ASN1_UTCTIME *s, const char *str)
|
||||
{
|
||||
ASN1_UTCTIME t;
|
||||
|
||||
t.type = V_ASN1_UTCTIME;
|
||||
t.length = strlen(str);
|
||||
t.data = (unsigned char *)str;
|
||||
if (ASN1_UTCTIME_check(&t)) {
|
||||
if (s != NULL) {
|
||||
if (!ASN1_STRING_set((ASN1_STRING *)s,
|
||||
(unsigned char *)str, t.length))
|
||||
return 0;
|
||||
s->type = V_ASN1_UTCTIME;
|
||||
}
|
||||
return (1);
|
||||
} else
|
||||
return (0);
|
||||
}
|
||||
|
||||
ASN1_UTCTIME *ASN1_UTCTIME_set(ASN1_UTCTIME *s, time_t t)
|
||||
{
|
||||
return ASN1_UTCTIME_adj(s, t, 0, 0);
|
||||
}
|
||||
|
||||
ASN1_UTCTIME *ASN1_UTCTIME_adj(ASN1_UTCTIME *s, time_t t,
|
||||
int offset_day, long offset_sec)
|
||||
{
|
||||
char *p;
|
||||
struct tm *ts;
|
||||
struct tm data;
|
||||
size_t len = 20;
|
||||
int free_s = 0;
|
||||
|
||||
if (s == NULL) {
|
||||
free_s = 1;
|
||||
s = M_ASN1_UTCTIME_new();
|
||||
}
|
||||
if (s == NULL)
|
||||
goto err;
|
||||
|
||||
ts = OPENSSL_gmtime(&t, &data);
|
||||
if (ts == NULL)
|
||||
goto err;
|
||||
|
||||
if (offset_day || offset_sec) {
|
||||
if (!OPENSSL_gmtime_adj(ts, offset_day, offset_sec))
|
||||
goto err;
|
||||
}
|
||||
|
||||
if ((ts->tm_year < 50) || (ts->tm_year >= 150))
|
||||
goto err;
|
||||
|
||||
p = (char *)s->data;
|
||||
if ((p == NULL) || ((size_t)s->length < len)) {
|
||||
p = OPENSSL_malloc(len);
|
||||
if (p == NULL) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
if (s->data != NULL)
|
||||
OPENSSL_free(s->data);
|
||||
s->data = (unsigned char *)p;
|
||||
}
|
||||
|
||||
BIO_snprintf(p, len, "%02d%02d%02d%02d%02d%02dZ", ts->tm_year % 100,
|
||||
ts->tm_mon + 1, ts->tm_mday, ts->tm_hour, ts->tm_min,
|
||||
ts->tm_sec);
|
||||
s->length = strlen(p);
|
||||
s->type = V_ASN1_UTCTIME;
|
||||
return (s);
|
||||
err:
|
||||
if (free_s && s)
|
||||
M_ASN1_UTCTIME_free(s);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int ASN1_UTCTIME_cmp_time_t(const ASN1_UTCTIME *s, time_t t)
|
||||
{
|
||||
struct tm stm, ttm;
|
||||
int day, sec;
|
||||
|
||||
if (!asn1_utctime_to_tm(&stm, s))
|
||||
return -2;
|
||||
|
||||
if (!OPENSSL_gmtime(&t, &ttm))
|
||||
return -2;
|
||||
|
||||
if (!OPENSSL_gmtime_diff(&day, &sec, &ttm, &stm))
|
||||
return -2;
|
||||
|
||||
if (day > 0)
|
||||
return 1;
|
||||
if (day < 0)
|
||||
return -1;
|
||||
if (sec > 0)
|
||||
return 1;
|
||||
if (sec < 0)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if 0
|
||||
time_t ASN1_UTCTIME_get(const ASN1_UTCTIME *s)
|
||||
{
|
||||
struct tm tm;
|
||||
int offset;
|
||||
|
||||
OPENSSL_memset(&tm, '\0', sizeof tm);
|
||||
|
||||
# define g2(p) (((p)[0]-'0')*10+(p)[1]-'0')
|
||||
tm.tm_year = g2(s->data);
|
||||
if (tm.tm_year < 50)
|
||||
tm.tm_year += 100;
|
||||
tm.tm_mon = g2(s->data + 2) - 1;
|
||||
tm.tm_mday = g2(s->data + 4);
|
||||
tm.tm_hour = g2(s->data + 6);
|
||||
tm.tm_min = g2(s->data + 8);
|
||||
tm.tm_sec = g2(s->data + 10);
|
||||
if (s->data[12] == 'Z')
|
||||
offset = 0;
|
||||
else {
|
||||
offset = g2(s->data + 13) * 60 + g2(s->data + 15);
|
||||
if (s->data[12] == '-')
|
||||
offset = -offset;
|
||||
}
|
||||
# undef g2
|
||||
|
||||
return mktime(&tm) - offset * 60; /* FIXME: mktime assumes the current
|
||||
* timezone instead of UTC, and unless
|
||||
* we rewrite OpenSSL in Lisp we cannot
|
||||
* locally change the timezone without
|
||||
* possibly interfering with other
|
||||
* parts of the program. timegm, which
|
||||
* uses UTC, is non-standard. Also
|
||||
* time_t is inappropriate for general
|
||||
* UTC times because it may a 32 bit
|
||||
* type. */
|
||||
}
|
||||
#endif
|
||||
+236
@@ -0,0 +1,236 @@
|
||||
/* Copyright (C) 1995-1998 Eric Young ([email protected])
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young ([email protected]).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson ([email protected]).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young ([email protected])"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson ([email protected])"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.] */
|
||||
|
||||
#include <openssl_grpc/asn1.h>
|
||||
|
||||
#include <openssl_grpc/err.h>
|
||||
#include <openssl_grpc/mem.h>
|
||||
|
||||
#include "asn1_locl.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, uint32_t *val)
|
||||
{
|
||||
const unsigned char *p;
|
||||
uint32_t 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 = ((uint32_t)(*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 = ((uint32_t)(*p++ & 0x3)) << 24;
|
||||
value |= ((uint32_t)(*p++ & 0x3f)) << 18;
|
||||
value |= ((uint32_t)(*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 = ((uint32_t)(*p++ & 0x1)) << 30;
|
||||
value |= ((uint32_t)(*p++ & 0x3f)) << 24;
|
||||
value |= ((uint32_t)(*p++ & 0x3f)) << 18;
|
||||
value |= ((uint32_t)(*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, uint32_t 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;
|
||||
}
|
||||
+236
@@ -0,0 +1,236 @@
|
||||
/* Copyright (C) 1995-1998 Eric Young ([email protected])
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young ([email protected]).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson ([email protected]).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young ([email protected])"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson ([email protected])"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.] */
|
||||
|
||||
#include <openssl/asn1.h>
|
||||
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/mem.h>
|
||||
|
||||
#include "asn1_locl.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, uint32_t *val)
|
||||
{
|
||||
const unsigned char *p;
|
||||
uint32_t 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 = ((uint32_t)(*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 = ((uint32_t)(*p++ & 0x3)) << 24;
|
||||
value |= ((uint32_t)(*p++ & 0x3f)) << 18;
|
||||
value |= ((uint32_t)(*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 = ((uint32_t)(*p++ & 0x1)) << 30;
|
||||
value |= ((uint32_t)(*p++ & 0x3f)) << 24;
|
||||
value |= ((uint32_t)(*p++ & 0x3f)) << 18;
|
||||
value |= ((uint32_t)(*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, uint32_t 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;
|
||||
}
|
||||
+446
@@ -0,0 +1,446 @@
|
||||
/* Copyright (C) 1995-1998 Eric Young ([email protected])
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young ([email protected]).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson ([email protected]).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young ([email protected])"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson ([email protected])"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.] */
|
||||
|
||||
#include <openssl_grpc/asn1.h>
|
||||
|
||||
#include <limits.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <openssl_grpc/asn1_mac.h>
|
||||
#include <openssl_grpc/err.h>
|
||||
#include <openssl_grpc/mem.h>
|
||||
|
||||
#include "../internal.h"
|
||||
|
||||
|
||||
/* Cross-module errors from crypto/x509/i2d_pr.c. */
|
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, UNSUPPORTED_PUBLIC_KEY_TYPE)
|
||||
|
||||
/* Cross-module errors from crypto/x509/algorithm.c. */
|
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, CONTEXT_NOT_INITIALISED)
|
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, DIGEST_AND_KEY_TYPE_NOT_SUPPORTED)
|
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, UNKNOWN_MESSAGE_DIGEST_ALGORITHM)
|
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, UNKNOWN_SIGNATURE_ALGORITHM)
|
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, WRONG_PUBLIC_KEY_TYPE)
|
||||
/*
|
||||
* Cross-module errors from crypto/x509/asn1_gen.c. TODO(davidben): Remove
|
||||
* these once asn1_gen.c is gone.
|
||||
*/
|
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, DEPTH_EXCEEDED)
|
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, ILLEGAL_BITSTRING_FORMAT)
|
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, ILLEGAL_BOOLEAN)
|
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, ILLEGAL_FORMAT)
|
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, ILLEGAL_HEX)
|
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, ILLEGAL_IMPLICIT_TAG)
|
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, ILLEGAL_INTEGER)
|
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, ILLEGAL_NESTED_TAGGING)
|
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, ILLEGAL_NULL_VALUE)
|
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, ILLEGAL_OBJECT)
|
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, ILLEGAL_TIME_VALUE)
|
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, INTEGER_NOT_ASCII_FORMAT)
|
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, INVALID_MODIFIER)
|
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, INVALID_NUMBER)
|
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, LIST_ERROR)
|
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, MISSING_VALUE)
|
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, NOT_ASCII_FORMAT)
|
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, OBJECT_NOT_ASCII_FORMAT)
|
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, SEQUENCE_OR_SET_NEEDS_CONFIG)
|
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, TIME_NOT_ASCII_FORMAT)
|
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, UNKNOWN_FORMAT)
|
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, UNKNOWN_TAG)
|
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, UNSUPPORTED_TYPE)
|
||||
|
||||
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);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/* To avoid ambiguity with V_ASN1_NEG, impose a limit on universal tags. */
|
||||
if (xclass == V_ASN1_UNIVERSAL && tag > V_ASN1_MAX_UNIVERSAL)
|
||||
goto err;
|
||||
|
||||
*ptag = tag;
|
||||
*pclass = xclass;
|
||||
if (!asn1_get_length(&p, &inf, plength, max))
|
||||
goto err;
|
||||
|
||||
if (inf && !(ret & V_ASN1_CONSTRUCTED))
|
||||
goto err;
|
||||
|
||||
#if 0
|
||||
fprintf(stderr, "p=%d + *plength=%ld > omax=%ld + *pp=%d (%d > %d)\n",
|
||||
(int)p, *plength, omax, (int)*pp, (int)(p + *plength),
|
||||
(int)(omax + *pp));
|
||||
|
||||
#endif
|
||||
if (*plength > (omax - (p - *pp))) {
|
||||
OPENSSL_PUT_ERROR(ASN1, 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:
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_HEADER_TOO_LONG);
|
||||
return (0x80);
|
||||
}
|
||||
|
||||
static int asn1_get_length(const unsigned char **pp, int *inf, long *rl,
|
||||
long max)
|
||||
{
|
||||
const unsigned char *p = *pp;
|
||||
unsigned long ret = 0;
|
||||
unsigned long i;
|
||||
|
||||
if (max-- < 1)
|
||||
return 0;
|
||||
if (*p == 0x80) {
|
||||
*inf = 1;
|
||||
ret = 0;
|
||||
p++;
|
||||
} else {
|
||||
*inf = 0;
|
||||
i = *p & 0x7f;
|
||||
if (*(p++) & 0x80) {
|
||||
if (i > sizeof(ret) || max < (long)i)
|
||||
return 0;
|
||||
while (i-- > 0) {
|
||||
ret <<= 8L;
|
||||
ret |= *(p++);
|
||||
}
|
||||
} else
|
||||
ret = i;
|
||||
}
|
||||
/*
|
||||
* Bound the length to comfortably fit in an int. Lengths in this module
|
||||
* often switch between int and long without overflow checks.
|
||||
*/
|
||||
if (ret > INT_MAX / 2)
|
||||
return 0;
|
||||
*pp = p;
|
||||
*rl = (long)ret;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* class 0 is constructed constructed == 2 for indefinite length constructed
|
||||
*/
|
||||
void ASN1_put_object(unsigned char **pp, int constructed, int length, int tag,
|
||||
int xclass)
|
||||
{
|
||||
unsigned char *p = *pp;
|
||||
int i, ttag;
|
||||
|
||||
i = (constructed) ? V_ASN1_CONSTRUCTED : 0;
|
||||
i |= (xclass & V_ASN1_PRIVATE);
|
||||
if (tag < 31)
|
||||
*(p++) = i | (tag & V_ASN1_PRIMITIVE_TAG);
|
||||
else {
|
||||
*(p++) = i | V_ASN1_PRIMITIVE_TAG;
|
||||
for (i = 0, ttag = tag; ttag > 0; i++)
|
||||
ttag >>= 7;
|
||||
ttag = i;
|
||||
while (i-- > 0) {
|
||||
p[i] = tag & 0x7f;
|
||||
if (i != (ttag - 1))
|
||||
p[i] |= 0x80;
|
||||
tag >>= 7;
|
||||
}
|
||||
p += ttag;
|
||||
}
|
||||
if (constructed == 2)
|
||||
*(p++) = 0x80;
|
||||
else
|
||||
asn1_put_length(&p, length);
|
||||
*pp = p;
|
||||
}
|
||||
|
||||
int ASN1_put_eoc(unsigned char **pp)
|
||||
{
|
||||
unsigned char *p = *pp;
|
||||
*p++ = 0;
|
||||
*p++ = 0;
|
||||
*pp = p;
|
||||
return 2;
|
||||
}
|
||||
|
||||
static void asn1_put_length(unsigned char **pp, int length)
|
||||
{
|
||||
unsigned char *p = *pp;
|
||||
int i, l;
|
||||
if (length <= 127)
|
||||
*(p++) = (unsigned char)length;
|
||||
else {
|
||||
l = length;
|
||||
for (i = 0; l > 0; i++)
|
||||
l >>= 8;
|
||||
*(p++) = i | 0x80;
|
||||
l = i;
|
||||
while (i-- > 0) {
|
||||
p[i] = length & 0xff;
|
||||
length >>= 8;
|
||||
}
|
||||
p += l;
|
||||
}
|
||||
*pp = p;
|
||||
}
|
||||
|
||||
int ASN1_object_size(int constructed, int length, int tag)
|
||||
{
|
||||
int ret = 1;
|
||||
if (length < 0)
|
||||
return -1;
|
||||
if (tag >= 31) {
|
||||
while (tag > 0) {
|
||||
tag >>= 7;
|
||||
ret++;
|
||||
}
|
||||
}
|
||||
if (constructed == 2) {
|
||||
ret += 3;
|
||||
} else {
|
||||
ret++;
|
||||
if (length > 127) {
|
||||
int tmplen = length;
|
||||
while (tmplen > 0) {
|
||||
tmplen >>= 8;
|
||||
ret++;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ret >= INT_MAX - length)
|
||||
return -1;
|
||||
return ret + length;
|
||||
}
|
||||
|
||||
int ASN1_STRING_copy(ASN1_STRING *dst, const ASN1_STRING *str)
|
||||
{
|
||||
if (str == NULL)
|
||||
return 0;
|
||||
dst->type = str->type;
|
||||
if (!ASN1_STRING_set(dst, str->data, str->length))
|
||||
return 0;
|
||||
dst->flags = str->flags;
|
||||
return 1;
|
||||
}
|
||||
|
||||
ASN1_STRING *ASN1_STRING_dup(const ASN1_STRING *str)
|
||||
{
|
||||
ASN1_STRING *ret;
|
||||
if (!str)
|
||||
return NULL;
|
||||
ret = ASN1_STRING_new();
|
||||
if (!ret)
|
||||
return NULL;
|
||||
if (!ASN1_STRING_copy(ret, str)) {
|
||||
ASN1_STRING_free(ret);
|
||||
return NULL;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ASN1_STRING_set(ASN1_STRING *str, const void *_data, int len)
|
||||
{
|
||||
unsigned char *c;
|
||||
const char *data = _data;
|
||||
|
||||
if (len < 0) {
|
||||
if (data == NULL)
|
||||
return (0);
|
||||
else
|
||||
len = strlen(data);
|
||||
}
|
||||
if ((str->length <= len) || (str->data == NULL)) {
|
||||
c = str->data;
|
||||
if (c == NULL)
|
||||
str->data = OPENSSL_malloc(len + 1);
|
||||
else
|
||||
str->data = OPENSSL_realloc(c, len + 1);
|
||||
|
||||
if (str->data == NULL) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
|
||||
str->data = c;
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
str->length = len;
|
||||
if (data != NULL) {
|
||||
OPENSSL_memcpy(str->data, data, len);
|
||||
/* an allowance for strings :-) */
|
||||
str->data[len] = '\0';
|
||||
}
|
||||
return (1);
|
||||
}
|
||||
|
||||
void ASN1_STRING_set0(ASN1_STRING *str, void *data, int len)
|
||||
{
|
||||
if (str->data)
|
||||
OPENSSL_free(str->data);
|
||||
str->data = data;
|
||||
str->length = len;
|
||||
}
|
||||
|
||||
ASN1_STRING *ASN1_STRING_new(void)
|
||||
{
|
||||
return (ASN1_STRING_type_new(V_ASN1_OCTET_STRING));
|
||||
}
|
||||
|
||||
ASN1_STRING *ASN1_STRING_type_new(int type)
|
||||
{
|
||||
ASN1_STRING *ret;
|
||||
|
||||
ret = (ASN1_STRING *)OPENSSL_malloc(sizeof(ASN1_STRING));
|
||||
if (ret == NULL) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
|
||||
return (NULL);
|
||||
}
|
||||
ret->length = 0;
|
||||
ret->type = type;
|
||||
ret->data = NULL;
|
||||
ret->flags = 0;
|
||||
return (ret);
|
||||
}
|
||||
|
||||
void ASN1_STRING_free(ASN1_STRING *a)
|
||||
{
|
||||
if (a == NULL)
|
||||
return;
|
||||
if (a->data && !(a->flags & ASN1_STRING_FLAG_NDEF))
|
||||
OPENSSL_free(a->data);
|
||||
OPENSSL_free(a);
|
||||
}
|
||||
|
||||
int ASN1_STRING_cmp(const ASN1_STRING *a, const ASN1_STRING *b)
|
||||
{
|
||||
int i;
|
||||
|
||||
i = (a->length - b->length);
|
||||
if (i == 0) {
|
||||
i = OPENSSL_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 M_ASN1_STRING_length(x);
|
||||
}
|
||||
|
||||
void ASN1_STRING_length_set(ASN1_STRING *x, int len)
|
||||
{
|
||||
M_ASN1_STRING_length_set(x, len);
|
||||
return;
|
||||
}
|
||||
|
||||
int ASN1_STRING_type(ASN1_STRING *x)
|
||||
{
|
||||
return M_ASN1_STRING_type(x);
|
||||
}
|
||||
|
||||
unsigned char *ASN1_STRING_data(ASN1_STRING *x)
|
||||
{
|
||||
return M_ASN1_STRING_data(x);
|
||||
}
|
||||
|
||||
const unsigned char *ASN1_STRING_get0_data(const ASN1_STRING *x)
|
||||
{
|
||||
return x->data;
|
||||
}
|
||||
@@ -0,0 +1,446 @@
|
||||
/* Copyright (C) 1995-1998 Eric Young ([email protected])
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young ([email protected]).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson ([email protected]).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young ([email protected])"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson ([email protected])"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.] */
|
||||
|
||||
#include <openssl/asn1.h>
|
||||
|
||||
#include <limits.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <openssl/asn1_mac.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/mem.h>
|
||||
|
||||
#include "../internal.h"
|
||||
|
||||
|
||||
/* Cross-module errors from crypto/x509/i2d_pr.c. */
|
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, UNSUPPORTED_PUBLIC_KEY_TYPE)
|
||||
|
||||
/* Cross-module errors from crypto/x509/algorithm.c. */
|
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, CONTEXT_NOT_INITIALISED)
|
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, DIGEST_AND_KEY_TYPE_NOT_SUPPORTED)
|
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, UNKNOWN_MESSAGE_DIGEST_ALGORITHM)
|
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, UNKNOWN_SIGNATURE_ALGORITHM)
|
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, WRONG_PUBLIC_KEY_TYPE)
|
||||
/*
|
||||
* Cross-module errors from crypto/x509/asn1_gen.c. TODO(davidben): Remove
|
||||
* these once asn1_gen.c is gone.
|
||||
*/
|
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, DEPTH_EXCEEDED)
|
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, ILLEGAL_BITSTRING_FORMAT)
|
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, ILLEGAL_BOOLEAN)
|
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, ILLEGAL_FORMAT)
|
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, ILLEGAL_HEX)
|
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, ILLEGAL_IMPLICIT_TAG)
|
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, ILLEGAL_INTEGER)
|
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, ILLEGAL_NESTED_TAGGING)
|
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, ILLEGAL_NULL_VALUE)
|
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, ILLEGAL_OBJECT)
|
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, ILLEGAL_TIME_VALUE)
|
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, INTEGER_NOT_ASCII_FORMAT)
|
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, INVALID_MODIFIER)
|
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, INVALID_NUMBER)
|
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, LIST_ERROR)
|
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, MISSING_VALUE)
|
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, NOT_ASCII_FORMAT)
|
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, OBJECT_NOT_ASCII_FORMAT)
|
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, SEQUENCE_OR_SET_NEEDS_CONFIG)
|
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, TIME_NOT_ASCII_FORMAT)
|
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, UNKNOWN_FORMAT)
|
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, UNKNOWN_TAG)
|
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, UNSUPPORTED_TYPE)
|
||||
|
||||
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);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/* To avoid ambiguity with V_ASN1_NEG, impose a limit on universal tags. */
|
||||
if (xclass == V_ASN1_UNIVERSAL && tag > V_ASN1_MAX_UNIVERSAL)
|
||||
goto err;
|
||||
|
||||
*ptag = tag;
|
||||
*pclass = xclass;
|
||||
if (!asn1_get_length(&p, &inf, plength, max))
|
||||
goto err;
|
||||
|
||||
if (inf && !(ret & V_ASN1_CONSTRUCTED))
|
||||
goto err;
|
||||
|
||||
#if 0
|
||||
fprintf(stderr, "p=%d + *plength=%ld > omax=%ld + *pp=%d (%d > %d)\n",
|
||||
(int)p, *plength, omax, (int)*pp, (int)(p + *plength),
|
||||
(int)(omax + *pp));
|
||||
|
||||
#endif
|
||||
if (*plength > (omax - (p - *pp))) {
|
||||
OPENSSL_PUT_ERROR(ASN1, 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:
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_HEADER_TOO_LONG);
|
||||
return (0x80);
|
||||
}
|
||||
|
||||
static int asn1_get_length(const unsigned char **pp, int *inf, long *rl,
|
||||
long max)
|
||||
{
|
||||
const unsigned char *p = *pp;
|
||||
unsigned long ret = 0;
|
||||
unsigned long i;
|
||||
|
||||
if (max-- < 1)
|
||||
return 0;
|
||||
if (*p == 0x80) {
|
||||
*inf = 1;
|
||||
ret = 0;
|
||||
p++;
|
||||
} else {
|
||||
*inf = 0;
|
||||
i = *p & 0x7f;
|
||||
if (*(p++) & 0x80) {
|
||||
if (i > sizeof(ret) || max < (long)i)
|
||||
return 0;
|
||||
while (i-- > 0) {
|
||||
ret <<= 8L;
|
||||
ret |= *(p++);
|
||||
}
|
||||
} else
|
||||
ret = i;
|
||||
}
|
||||
/*
|
||||
* Bound the length to comfortably fit in an int. Lengths in this module
|
||||
* often switch between int and long without overflow checks.
|
||||
*/
|
||||
if (ret > INT_MAX / 2)
|
||||
return 0;
|
||||
*pp = p;
|
||||
*rl = (long)ret;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* class 0 is constructed constructed == 2 for indefinite length constructed
|
||||
*/
|
||||
void ASN1_put_object(unsigned char **pp, int constructed, int length, int tag,
|
||||
int xclass)
|
||||
{
|
||||
unsigned char *p = *pp;
|
||||
int i, ttag;
|
||||
|
||||
i = (constructed) ? V_ASN1_CONSTRUCTED : 0;
|
||||
i |= (xclass & V_ASN1_PRIVATE);
|
||||
if (tag < 31)
|
||||
*(p++) = i | (tag & V_ASN1_PRIMITIVE_TAG);
|
||||
else {
|
||||
*(p++) = i | V_ASN1_PRIMITIVE_TAG;
|
||||
for (i = 0, ttag = tag; ttag > 0; i++)
|
||||
ttag >>= 7;
|
||||
ttag = i;
|
||||
while (i-- > 0) {
|
||||
p[i] = tag & 0x7f;
|
||||
if (i != (ttag - 1))
|
||||
p[i] |= 0x80;
|
||||
tag >>= 7;
|
||||
}
|
||||
p += ttag;
|
||||
}
|
||||
if (constructed == 2)
|
||||
*(p++) = 0x80;
|
||||
else
|
||||
asn1_put_length(&p, length);
|
||||
*pp = p;
|
||||
}
|
||||
|
||||
int ASN1_put_eoc(unsigned char **pp)
|
||||
{
|
||||
unsigned char *p = *pp;
|
||||
*p++ = 0;
|
||||
*p++ = 0;
|
||||
*pp = p;
|
||||
return 2;
|
||||
}
|
||||
|
||||
static void asn1_put_length(unsigned char **pp, int length)
|
||||
{
|
||||
unsigned char *p = *pp;
|
||||
int i, l;
|
||||
if (length <= 127)
|
||||
*(p++) = (unsigned char)length;
|
||||
else {
|
||||
l = length;
|
||||
for (i = 0; l > 0; i++)
|
||||
l >>= 8;
|
||||
*(p++) = i | 0x80;
|
||||
l = i;
|
||||
while (i-- > 0) {
|
||||
p[i] = length & 0xff;
|
||||
length >>= 8;
|
||||
}
|
||||
p += l;
|
||||
}
|
||||
*pp = p;
|
||||
}
|
||||
|
||||
int ASN1_object_size(int constructed, int length, int tag)
|
||||
{
|
||||
int ret = 1;
|
||||
if (length < 0)
|
||||
return -1;
|
||||
if (tag >= 31) {
|
||||
while (tag > 0) {
|
||||
tag >>= 7;
|
||||
ret++;
|
||||
}
|
||||
}
|
||||
if (constructed == 2) {
|
||||
ret += 3;
|
||||
} else {
|
||||
ret++;
|
||||
if (length > 127) {
|
||||
int tmplen = length;
|
||||
while (tmplen > 0) {
|
||||
tmplen >>= 8;
|
||||
ret++;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ret >= INT_MAX - length)
|
||||
return -1;
|
||||
return ret + length;
|
||||
}
|
||||
|
||||
int ASN1_STRING_copy(ASN1_STRING *dst, const ASN1_STRING *str)
|
||||
{
|
||||
if (str == NULL)
|
||||
return 0;
|
||||
dst->type = str->type;
|
||||
if (!ASN1_STRING_set(dst, str->data, str->length))
|
||||
return 0;
|
||||
dst->flags = str->flags;
|
||||
return 1;
|
||||
}
|
||||
|
||||
ASN1_STRING *ASN1_STRING_dup(const ASN1_STRING *str)
|
||||
{
|
||||
ASN1_STRING *ret;
|
||||
if (!str)
|
||||
return NULL;
|
||||
ret = ASN1_STRING_new();
|
||||
if (!ret)
|
||||
return NULL;
|
||||
if (!ASN1_STRING_copy(ret, str)) {
|
||||
ASN1_STRING_free(ret);
|
||||
return NULL;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ASN1_STRING_set(ASN1_STRING *str, const void *_data, int len)
|
||||
{
|
||||
unsigned char *c;
|
||||
const char *data = _data;
|
||||
|
||||
if (len < 0) {
|
||||
if (data == NULL)
|
||||
return (0);
|
||||
else
|
||||
len = strlen(data);
|
||||
}
|
||||
if ((str->length <= len) || (str->data == NULL)) {
|
||||
c = str->data;
|
||||
if (c == NULL)
|
||||
str->data = OPENSSL_malloc(len + 1);
|
||||
else
|
||||
str->data = OPENSSL_realloc(c, len + 1);
|
||||
|
||||
if (str->data == NULL) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
|
||||
str->data = c;
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
str->length = len;
|
||||
if (data != NULL) {
|
||||
OPENSSL_memcpy(str->data, data, len);
|
||||
/* an allowance for strings :-) */
|
||||
str->data[len] = '\0';
|
||||
}
|
||||
return (1);
|
||||
}
|
||||
|
||||
void ASN1_STRING_set0(ASN1_STRING *str, void *data, int len)
|
||||
{
|
||||
if (str->data)
|
||||
OPENSSL_free(str->data);
|
||||
str->data = data;
|
||||
str->length = len;
|
||||
}
|
||||
|
||||
ASN1_STRING *ASN1_STRING_new(void)
|
||||
{
|
||||
return (ASN1_STRING_type_new(V_ASN1_OCTET_STRING));
|
||||
}
|
||||
|
||||
ASN1_STRING *ASN1_STRING_type_new(int type)
|
||||
{
|
||||
ASN1_STRING *ret;
|
||||
|
||||
ret = (ASN1_STRING *)OPENSSL_malloc(sizeof(ASN1_STRING));
|
||||
if (ret == NULL) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
|
||||
return (NULL);
|
||||
}
|
||||
ret->length = 0;
|
||||
ret->type = type;
|
||||
ret->data = NULL;
|
||||
ret->flags = 0;
|
||||
return (ret);
|
||||
}
|
||||
|
||||
void ASN1_STRING_free(ASN1_STRING *a)
|
||||
{
|
||||
if (a == NULL)
|
||||
return;
|
||||
if (a->data && !(a->flags & ASN1_STRING_FLAG_NDEF))
|
||||
OPENSSL_free(a->data);
|
||||
OPENSSL_free(a);
|
||||
}
|
||||
|
||||
int ASN1_STRING_cmp(const ASN1_STRING *a, const ASN1_STRING *b)
|
||||
{
|
||||
int i;
|
||||
|
||||
i = (a->length - b->length);
|
||||
if (i == 0) {
|
||||
i = OPENSSL_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 M_ASN1_STRING_length(x);
|
||||
}
|
||||
|
||||
void ASN1_STRING_length_set(ASN1_STRING *x, int len)
|
||||
{
|
||||
M_ASN1_STRING_length_set(x, len);
|
||||
return;
|
||||
}
|
||||
|
||||
int ASN1_STRING_type(ASN1_STRING *x)
|
||||
{
|
||||
return M_ASN1_STRING_type(x);
|
||||
}
|
||||
|
||||
unsigned char *ASN1_STRING_data(ASN1_STRING *x)
|
||||
{
|
||||
return M_ASN1_STRING_data(x);
|
||||
}
|
||||
|
||||
const unsigned char *ASN1_STRING_get0_data(const ASN1_STRING *x)
|
||||
{
|
||||
return x->data;
|
||||
}
|
||||
+104
@@ -0,0 +1,104 @@
|
||||
/* asn1t.h */
|
||||
/*
|
||||
* Written by Dr Stephen N Henson ([email protected]) for the OpenSSL project
|
||||
* 2006.
|
||||
*/
|
||||
/* ====================================================================
|
||||
* Copyright (c) 2006 The OpenSSL Project. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* 3. All advertising materials mentioning features or use of this
|
||||
* software must display the following acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
|
||||
*
|
||||
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
|
||||
* endorse or promote products derived from this software without
|
||||
* prior written permission. For written permission, please contact
|
||||
* [email protected].
|
||||
*
|
||||
* 5. Products derived from this software may not be called "OpenSSL"
|
||||
* nor may "OpenSSL" appear in their names without prior written
|
||||
* permission of the OpenSSL Project.
|
||||
*
|
||||
* 6. Redistributions of any form whatsoever must retain the following
|
||||
* acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
|
||||
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
|
||||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ====================================================================
|
||||
*
|
||||
* This product includes cryptographic software written by Eric Young
|
||||
* ([email protected]). This product includes software written by Tim
|
||||
* Hudson ([email protected]).
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef OPENSSL_HEADER_ASN1_ASN1_LOCL_H
|
||||
#define OPENSSL_HEADER_ASN1_ASN1_LOCL_H
|
||||
|
||||
#include <time.h>
|
||||
|
||||
#include <openssl_grpc/asn1.h>
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
/* Wrapper functions for time functions. */
|
||||
|
||||
/* OPENSSL_gmtime wraps |gmtime_r|. See the manual page for that function. */
|
||||
struct tm *OPENSSL_gmtime(const time_t *time, struct tm *result);
|
||||
|
||||
/* OPENSSL_gmtime_adj updates |tm| by adding |offset_day| days and |offset_sec|
|
||||
* seconds. */
|
||||
int OPENSSL_gmtime_adj(struct tm *tm, int offset_day, long offset_sec);
|
||||
|
||||
/* OPENSSL_gmtime_diff calculates the difference between |from| and |to| and
|
||||
* outputs the difference as a number of days and seconds in |*out_days| and
|
||||
* |*out_secs|. */
|
||||
int OPENSSL_gmtime_diff(int *out_days, int *out_secs, const struct tm *from,
|
||||
const struct tm *to);
|
||||
|
||||
|
||||
/* Internal ASN1 structures and functions: not for application use */
|
||||
|
||||
int asn1_utctime_to_tm(struct tm *tm, const ASN1_UTCTIME *d);
|
||||
int asn1_generalizedtime_to_tm(struct tm *tm, const ASN1_GENERALIZEDTIME *d);
|
||||
|
||||
void asn1_item_combine_free(ASN1_VALUE **pval, const ASN1_ITEM *it,
|
||||
int combine);
|
||||
|
||||
int UTF8_getc(const unsigned char *str, int len, uint32_t *val);
|
||||
int UTF8_putc(unsigned char *str, int len, uint32_t value);
|
||||
|
||||
|
||||
#if defined(__cplusplus)
|
||||
} /* extern C */
|
||||
#endif
|
||||
|
||||
#endif /* OPENSSL_HEADER_ASN1_ASN1_LOCL_H */
|
||||
@@ -0,0 +1,104 @@
|
||||
/* asn1t.h */
|
||||
/*
|
||||
* Written by Dr Stephen N Henson ([email protected]) for the OpenSSL project
|
||||
* 2006.
|
||||
*/
|
||||
/* ====================================================================
|
||||
* Copyright (c) 2006 The OpenSSL Project. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* 3. All advertising materials mentioning features or use of this
|
||||
* software must display the following acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
|
||||
*
|
||||
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
|
||||
* endorse or promote products derived from this software without
|
||||
* prior written permission. For written permission, please contact
|
||||
* [email protected].
|
||||
*
|
||||
* 5. Products derived from this software may not be called "OpenSSL"
|
||||
* nor may "OpenSSL" appear in their names without prior written
|
||||
* permission of the OpenSSL Project.
|
||||
*
|
||||
* 6. Redistributions of any form whatsoever must retain the following
|
||||
* acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
|
||||
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
|
||||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ====================================================================
|
||||
*
|
||||
* This product includes cryptographic software written by Eric Young
|
||||
* ([email protected]). This product includes software written by Tim
|
||||
* Hudson ([email protected]).
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef OPENSSL_HEADER_ASN1_ASN1_LOCL_H
|
||||
#define OPENSSL_HEADER_ASN1_ASN1_LOCL_H
|
||||
|
||||
#include <time.h>
|
||||
|
||||
#include <openssl/asn1.h>
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
/* Wrapper functions for time functions. */
|
||||
|
||||
/* OPENSSL_gmtime wraps |gmtime_r|. See the manual page for that function. */
|
||||
struct tm *OPENSSL_gmtime(const time_t *time, struct tm *result);
|
||||
|
||||
/* OPENSSL_gmtime_adj updates |tm| by adding |offset_day| days and |offset_sec|
|
||||
* seconds. */
|
||||
int OPENSSL_gmtime_adj(struct tm *tm, int offset_day, long offset_sec);
|
||||
|
||||
/* OPENSSL_gmtime_diff calculates the difference between |from| and |to| and
|
||||
* outputs the difference as a number of days and seconds in |*out_days| and
|
||||
* |*out_secs|. */
|
||||
int OPENSSL_gmtime_diff(int *out_days, int *out_secs, const struct tm *from,
|
||||
const struct tm *to);
|
||||
|
||||
|
||||
/* Internal ASN1 structures and functions: not for application use */
|
||||
|
||||
int asn1_utctime_to_tm(struct tm *tm, const ASN1_UTCTIME *d);
|
||||
int asn1_generalizedtime_to_tm(struct tm *tm, const ASN1_GENERALIZEDTIME *d);
|
||||
|
||||
void asn1_item_combine_free(ASN1_VALUE **pval, const ASN1_ITEM *it,
|
||||
int combine);
|
||||
|
||||
int UTF8_getc(const unsigned char *str, int len, uint32_t *val);
|
||||
int UTF8_putc(unsigned char *str, int len, uint32_t value);
|
||||
|
||||
|
||||
#if defined(__cplusplus)
|
||||
} /* extern C */
|
||||
#endif
|
||||
|
||||
#endif /* OPENSSL_HEADER_ASN1_ASN1_LOCL_H */
|
||||
+80
@@ -0,0 +1,80 @@
|
||||
/* Copyright (C) 1995-1998 Eric Young ([email protected])
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young ([email protected]).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson ([email protected]).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young ([email protected])"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson ([email protected])"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.] */
|
||||
|
||||
#include <openssl_grpc/asn1.h>
|
||||
|
||||
|
||||
const char *ASN1_tag2str(int tag)
|
||||
{
|
||||
static const char *const tag2str[] = {
|
||||
"EOC", "BOOLEAN", "INTEGER", "BIT STRING", "OCTET STRING", /* 0-4 */
|
||||
"NULL", "OBJECT", "OBJECT DESCRIPTOR", "EXTERNAL", "REAL", /* 5-9 */
|
||||
"ENUMERATED", "<ASN1 11>", "UTF8STRING", "<ASN1 13>", /* 10-13 */
|
||||
"<ASN1 14>", "<ASN1 15>", "SEQUENCE", "SET", /* 15-17 */
|
||||
"NUMERICSTRING", "PRINTABLESTRING", "T61STRING", /* 18-20 */
|
||||
"VIDEOTEXSTRING", "IA5STRING", "UTCTIME", "GENERALIZEDTIME", /* 21-24
|
||||
*/
|
||||
"GRAPHICSTRING", "VISIBLESTRING", "GENERALSTRING", /* 25-27 */
|
||||
"UNIVERSALSTRING", "<ASN1 29>", "BMPSTRING" /* 28-30 */
|
||||
};
|
||||
|
||||
if ((tag == V_ASN1_NEG_INTEGER) || (tag == V_ASN1_NEG_ENUMERATED))
|
||||
tag &= ~0x100;
|
||||
|
||||
if (tag < 0 || tag > 30)
|
||||
return "(unknown)";
|
||||
return tag2str[tag];
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
/* Copyright (C) 1995-1998 Eric Young ([email protected])
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young ([email protected]).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson ([email protected]).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young ([email protected])"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson ([email protected])"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.] */
|
||||
|
||||
#include <openssl/asn1.h>
|
||||
|
||||
|
||||
const char *ASN1_tag2str(int tag)
|
||||
{
|
||||
static const char *const tag2str[] = {
|
||||
"EOC", "BOOLEAN", "INTEGER", "BIT STRING", "OCTET STRING", /* 0-4 */
|
||||
"NULL", "OBJECT", "OBJECT DESCRIPTOR", "EXTERNAL", "REAL", /* 5-9 */
|
||||
"ENUMERATED", "<ASN1 11>", "UTF8STRING", "<ASN1 13>", /* 10-13 */
|
||||
"<ASN1 14>", "<ASN1 15>", "SEQUENCE", "SET", /* 15-17 */
|
||||
"NUMERICSTRING", "PRINTABLESTRING", "T61STRING", /* 18-20 */
|
||||
"VIDEOTEXSTRING", "IA5STRING", "UTCTIME", "GENERALIZEDTIME", /* 21-24
|
||||
*/
|
||||
"GRAPHICSTRING", "VISIBLESTRING", "GENERALSTRING", /* 25-27 */
|
||||
"UNIVERSALSTRING", "<ASN1 29>", "BMPSTRING" /* 28-30 */
|
||||
};
|
||||
|
||||
if ((tag == V_ASN1_NEG_INTEGER) || (tag == V_ASN1_NEG_ENUMERATED))
|
||||
tag &= ~0x100;
|
||||
|
||||
if (tag < 0 || tag > 30)
|
||||
return "(unknown)";
|
||||
return tag2str[tag];
|
||||
}
|
||||
+105
@@ -0,0 +1,105 @@
|
||||
/* Copyright (C) 1995-1998 Eric Young ([email protected])
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young ([email protected]).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson ([email protected]).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young ([email protected])"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson ([email protected])"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.] */
|
||||
|
||||
#include <openssl_grpc/asn1.h>
|
||||
|
||||
#include <openssl_grpc/err.h>
|
||||
#include <openssl_grpc/mem.h>
|
||||
|
||||
/* ASN1_ITEM versions of the above */
|
||||
|
||||
ASN1_STRING *ASN1_item_pack(void *obj, const ASN1_ITEM *it, ASN1_STRING **oct)
|
||||
{
|
||||
ASN1_STRING *octmp;
|
||||
|
||||
if (!oct || !*oct) {
|
||||
if (!(octmp = ASN1_STRING_new())) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
|
||||
return NULL;
|
||||
}
|
||||
if (oct)
|
||||
*oct = octmp;
|
||||
} else
|
||||
octmp = *oct;
|
||||
|
||||
if (octmp->data) {
|
||||
OPENSSL_free(octmp->data);
|
||||
octmp->data = NULL;
|
||||
}
|
||||
|
||||
if (!(octmp->length = ASN1_item_i2d(obj, &octmp->data, it))) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_ENCODE_ERROR);
|
||||
return NULL;
|
||||
}
|
||||
if (!octmp->data) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
|
||||
return NULL;
|
||||
}
|
||||
return octmp;
|
||||
}
|
||||
|
||||
/* Extract an ASN1 object from an ASN1_STRING */
|
||||
|
||||
void *ASN1_item_unpack(ASN1_STRING *oct, const ASN1_ITEM *it)
|
||||
{
|
||||
const unsigned char *p;
|
||||
void *ret;
|
||||
|
||||
p = oct->data;
|
||||
if (!(ret = ASN1_item_d2i(NULL, &p, oct->length, it)))
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_DECODE_ERROR);
|
||||
return ret;
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
/* Copyright (C) 1995-1998 Eric Young ([email protected])
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young ([email protected]).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson ([email protected]).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young ([email protected])"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson ([email protected])"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.] */
|
||||
|
||||
#include <openssl/asn1.h>
|
||||
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/mem.h>
|
||||
|
||||
/* ASN1_ITEM versions of the above */
|
||||
|
||||
ASN1_STRING *ASN1_item_pack(void *obj, const ASN1_ITEM *it, ASN1_STRING **oct)
|
||||
{
|
||||
ASN1_STRING *octmp;
|
||||
|
||||
if (!oct || !*oct) {
|
||||
if (!(octmp = ASN1_STRING_new())) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
|
||||
return NULL;
|
||||
}
|
||||
if (oct)
|
||||
*oct = octmp;
|
||||
} else
|
||||
octmp = *oct;
|
||||
|
||||
if (octmp->data) {
|
||||
OPENSSL_free(octmp->data);
|
||||
octmp->data = NULL;
|
||||
}
|
||||
|
||||
if (!(octmp->length = ASN1_item_i2d(obj, &octmp->data, it))) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_ENCODE_ERROR);
|
||||
return NULL;
|
||||
}
|
||||
if (!octmp->data) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
|
||||
return NULL;
|
||||
}
|
||||
return octmp;
|
||||
}
|
||||
|
||||
/* Extract an ASN1 object from an ASN1_STRING */
|
||||
|
||||
void *ASN1_item_unpack(ASN1_STRING *oct, const ASN1_ITEM *it)
|
||||
{
|
||||
const unsigned char *p;
|
||||
void *ret;
|
||||
|
||||
p = oct->data;
|
||||
if (!(ret = ASN1_item_d2i(NULL, &p, oct->length, it)))
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_DECODE_ERROR);
|
||||
return ret;
|
||||
}
|
||||
+93
@@ -0,0 +1,93 @@
|
||||
/* Copyright (C) 1995-1998 Eric Young ([email protected])
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young ([email protected]).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson ([email protected]).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young ([email protected])"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson ([email protected])"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.] */
|
||||
|
||||
#include <openssl_grpc/asn1.h>
|
||||
|
||||
#include <openssl_grpc/bio.h>
|
||||
|
||||
/* Based on a_int.c: equivalent ENUMERATED functions */
|
||||
|
||||
int i2a_ASN1_ENUMERATED(BIO *bp, ASN1_ENUMERATED *a)
|
||||
{
|
||||
int i, n = 0;
|
||||
static const char *h = "0123456789ABCDEF";
|
||||
char buf[2];
|
||||
|
||||
if (a == NULL)
|
||||
return (0);
|
||||
|
||||
if (a->length == 0) {
|
||||
if (BIO_write(bp, "00", 2) != 2)
|
||||
goto err;
|
||||
n = 2;
|
||||
} else {
|
||||
for (i = 0; i < a->length; i++) {
|
||||
if ((i != 0) && (i % 35 == 0)) {
|
||||
if (BIO_write(bp, "\\\n", 2) != 2)
|
||||
goto err;
|
||||
n += 2;
|
||||
}
|
||||
buf[0] = h[((unsigned char)a->data[i] >> 4) & 0x0f];
|
||||
buf[1] = h[((unsigned char)a->data[i]) & 0x0f];
|
||||
if (BIO_write(bp, buf, 2) != 2)
|
||||
goto err;
|
||||
n += 2;
|
||||
}
|
||||
}
|
||||
return (n);
|
||||
err:
|
||||
return (-1);
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
/* Copyright (C) 1995-1998 Eric Young ([email protected])
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young ([email protected]).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson ([email protected]).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young ([email protected])"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson ([email protected])"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.] */
|
||||
|
||||
#include <openssl/asn1.h>
|
||||
|
||||
#include <openssl/bio.h>
|
||||
|
||||
/* Based on a_int.c: equivalent ENUMERATED functions */
|
||||
|
||||
int i2a_ASN1_ENUMERATED(BIO *bp, ASN1_ENUMERATED *a)
|
||||
{
|
||||
int i, n = 0;
|
||||
static const char *h = "0123456789ABCDEF";
|
||||
char buf[2];
|
||||
|
||||
if (a == NULL)
|
||||
return (0);
|
||||
|
||||
if (a->length == 0) {
|
||||
if (BIO_write(bp, "00", 2) != 2)
|
||||
goto err;
|
||||
n = 2;
|
||||
} else {
|
||||
for (i = 0; i < a->length; i++) {
|
||||
if ((i != 0) && (i % 35 == 0)) {
|
||||
if (BIO_write(bp, "\\\n", 2) != 2)
|
||||
goto err;
|
||||
n += 2;
|
||||
}
|
||||
buf[0] = h[((unsigned char)a->data[i] >> 4) & 0x0f];
|
||||
buf[1] = h[((unsigned char)a->data[i]) & 0x0f];
|
||||
if (BIO_write(bp, buf, 2) != 2)
|
||||
goto err;
|
||||
n += 2;
|
||||
}
|
||||
}
|
||||
return (n);
|
||||
err:
|
||||
return (-1);
|
||||
}
|
||||
+97
@@ -0,0 +1,97 @@
|
||||
/* Copyright (C) 1995-1998 Eric Young ([email protected])
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young ([email protected]).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson ([email protected]).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young ([email protected])"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson ([email protected])"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.] */
|
||||
|
||||
#include <openssl_grpc/asn1.h>
|
||||
|
||||
#include <openssl_grpc/bio.h>
|
||||
|
||||
int i2a_ASN1_INTEGER(BIO *bp, ASN1_INTEGER *a)
|
||||
{
|
||||
int i, n = 0;
|
||||
static const char *h = "0123456789ABCDEF";
|
||||
char buf[2];
|
||||
|
||||
if (a == NULL)
|
||||
return (0);
|
||||
|
||||
if (a->type & V_ASN1_NEG) {
|
||||
if (BIO_write(bp, "-", 1) != 1)
|
||||
goto err;
|
||||
n = 1;
|
||||
}
|
||||
|
||||
if (a->length == 0) {
|
||||
if (BIO_write(bp, "00", 2) != 2)
|
||||
goto err;
|
||||
n += 2;
|
||||
} else {
|
||||
for (i = 0; i < a->length; i++) {
|
||||
if ((i != 0) && (i % 35 == 0)) {
|
||||
if (BIO_write(bp, "\\\n", 2) != 2)
|
||||
goto err;
|
||||
n += 2;
|
||||
}
|
||||
buf[0] = h[((unsigned char)a->data[i] >> 4) & 0x0f];
|
||||
buf[1] = h[((unsigned char)a->data[i]) & 0x0f];
|
||||
if (BIO_write(bp, buf, 2) != 2)
|
||||
goto err;
|
||||
n += 2;
|
||||
}
|
||||
}
|
||||
return (n);
|
||||
err:
|
||||
return (-1);
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
/* Copyright (C) 1995-1998 Eric Young ([email protected])
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young ([email protected]).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson ([email protected]).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young ([email protected])"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson ([email protected])"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.] */
|
||||
|
||||
#include <openssl/asn1.h>
|
||||
|
||||
#include <openssl/bio.h>
|
||||
|
||||
int i2a_ASN1_INTEGER(BIO *bp, ASN1_INTEGER *a)
|
||||
{
|
||||
int i, n = 0;
|
||||
static const char *h = "0123456789ABCDEF";
|
||||
char buf[2];
|
||||
|
||||
if (a == NULL)
|
||||
return (0);
|
||||
|
||||
if (a->type & V_ASN1_NEG) {
|
||||
if (BIO_write(bp, "-", 1) != 1)
|
||||
goto err;
|
||||
n = 1;
|
||||
}
|
||||
|
||||
if (a->length == 0) {
|
||||
if (BIO_write(bp, "00", 2) != 2)
|
||||
goto err;
|
||||
n += 2;
|
||||
} else {
|
||||
for (i = 0; i < a->length; i++) {
|
||||
if ((i != 0) && (i % 35 == 0)) {
|
||||
if (BIO_write(bp, "\\\n", 2) != 2)
|
||||
goto err;
|
||||
n += 2;
|
||||
}
|
||||
buf[0] = h[((unsigned char)a->data[i] >> 4) & 0x0f];
|
||||
buf[1] = h[((unsigned char)a->data[i]) & 0x0f];
|
||||
if (BIO_write(bp, buf, 2) != 2)
|
||||
goto err;
|
||||
n += 2;
|
||||
}
|
||||
}
|
||||
return (n);
|
||||
err:
|
||||
return (-1);
|
||||
}
|
||||
+91
@@ -0,0 +1,91 @@
|
||||
/* Copyright (C) 1995-1998 Eric Young ([email protected])
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young ([email protected]).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson ([email protected]).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young ([email protected])"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson ([email protected])"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.] */
|
||||
|
||||
#include <openssl_grpc/asn1.h>
|
||||
|
||||
#include <openssl_grpc/bio.h>
|
||||
|
||||
int i2a_ASN1_STRING(BIO *bp, ASN1_STRING *a, int type)
|
||||
{
|
||||
int i, n = 0;
|
||||
static const char *h = "0123456789ABCDEF";
|
||||
char buf[2];
|
||||
|
||||
if (a == NULL)
|
||||
return (0);
|
||||
|
||||
if (a->length == 0) {
|
||||
if (BIO_write(bp, "0", 1) != 1)
|
||||
goto err;
|
||||
n = 1;
|
||||
} else {
|
||||
for (i = 0; i < a->length; i++) {
|
||||
if ((i != 0) && (i % 35 == 0)) {
|
||||
if (BIO_write(bp, "\\\n", 2) != 2)
|
||||
goto err;
|
||||
n += 2;
|
||||
}
|
||||
buf[0] = h[((unsigned char)a->data[i] >> 4) & 0x0f];
|
||||
buf[1] = h[((unsigned char)a->data[i]) & 0x0f];
|
||||
if (BIO_write(bp, buf, 2) != 2)
|
||||
goto err;
|
||||
n += 2;
|
||||
}
|
||||
}
|
||||
return (n);
|
||||
err:
|
||||
return (-1);
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
/* Copyright (C) 1995-1998 Eric Young ([email protected])
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young ([email protected]).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson ([email protected]).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young ([email protected])"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson ([email protected])"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.] */
|
||||
|
||||
#include <openssl/asn1.h>
|
||||
|
||||
#include <openssl/bio.h>
|
||||
|
||||
int i2a_ASN1_STRING(BIO *bp, ASN1_STRING *a, int type)
|
||||
{
|
||||
int i, n = 0;
|
||||
static const char *h = "0123456789ABCDEF";
|
||||
char buf[2];
|
||||
|
||||
if (a == NULL)
|
||||
return (0);
|
||||
|
||||
if (a->length == 0) {
|
||||
if (BIO_write(bp, "0", 1) != 1)
|
||||
goto err;
|
||||
n = 1;
|
||||
} else {
|
||||
for (i = 0; i < a->length; i++) {
|
||||
if ((i != 0) && (i % 35 == 0)) {
|
||||
if (BIO_write(bp, "\\\n", 2) != 2)
|
||||
goto err;
|
||||
n += 2;
|
||||
}
|
||||
buf[0] = h[((unsigned char)a->data[i] >> 4) & 0x0f];
|
||||
buf[1] = h[((unsigned char)a->data[i]) & 0x0f];
|
||||
if (BIO_write(bp, buf, 2) != 2)
|
||||
goto err;
|
||||
n += 2;
|
||||
}
|
||||
}
|
||||
return (n);
|
||||
err:
|
||||
return (-1);
|
||||
}
|
||||
+1244
File diff suppressed because it is too large
Load Diff
+1244
File diff suppressed because it is too large
Load Diff
+664
@@ -0,0 +1,664 @@
|
||||
/* Copyright (C) 1995-1998 Eric Young ([email protected])
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young ([email protected]).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson ([email protected]).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young ([email protected])"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson ([email protected])"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.] */
|
||||
|
||||
#include <openssl_grpc/asn1.h>
|
||||
|
||||
#include <limits.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <openssl_grpc/asn1t.h>
|
||||
#include <openssl_grpc/mem.h>
|
||||
|
||||
#include "../internal.h"
|
||||
|
||||
|
||||
static int asn1_i2d_ex_primitive(ASN1_VALUE **pval, unsigned char **out,
|
||||
const ASN1_ITEM *it, int tag, int aclass);
|
||||
static int asn1_set_seq_out(STACK_OF(ASN1_VALUE) *sk, unsigned char **out,
|
||||
int skcontlen, const ASN1_ITEM *item,
|
||||
int do_sort, int iclass);
|
||||
static int asn1_template_ex_i2d(ASN1_VALUE **pval, unsigned char **out,
|
||||
const ASN1_TEMPLATE *tt, int tag, int aclass);
|
||||
static int asn1_item_flags_i2d(ASN1_VALUE *val, unsigned char **out,
|
||||
const ASN1_ITEM *it, int flags);
|
||||
|
||||
/*
|
||||
* Top level i2d equivalents: the 'ndef' variant instructs the encoder to use
|
||||
* indefinite length constructed encoding, where appropriate
|
||||
*/
|
||||
|
||||
int ASN1_item_ndef_i2d(ASN1_VALUE *val, unsigned char **out,
|
||||
const ASN1_ITEM *it)
|
||||
{
|
||||
return asn1_item_flags_i2d(val, out, it, ASN1_TFLG_NDEF);
|
||||
}
|
||||
|
||||
int ASN1_item_i2d(ASN1_VALUE *val, unsigned char **out, const ASN1_ITEM *it)
|
||||
{
|
||||
return asn1_item_flags_i2d(val, out, it, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Encode an ASN1 item, this is use by the standard 'i2d' function. 'out'
|
||||
* points to a buffer to output the data to. The new i2d has one additional
|
||||
* feature. If the output buffer is NULL (i.e. *out == NULL) then a buffer is
|
||||
* allocated and populated with the encoding.
|
||||
*/
|
||||
|
||||
static int asn1_item_flags_i2d(ASN1_VALUE *val, unsigned char **out,
|
||||
const ASN1_ITEM *it, int flags)
|
||||
{
|
||||
if (out && !*out) {
|
||||
unsigned char *p, *buf;
|
||||
int len;
|
||||
len = ASN1_item_ex_i2d(&val, NULL, it, -1, flags);
|
||||
if (len <= 0)
|
||||
return len;
|
||||
buf = OPENSSL_malloc(len);
|
||||
if (!buf)
|
||||
return -1;
|
||||
p = buf;
|
||||
ASN1_item_ex_i2d(&val, &p, it, -1, flags);
|
||||
*out = buf;
|
||||
return len;
|
||||
}
|
||||
|
||||
return ASN1_item_ex_i2d(&val, out, it, -1, flags);
|
||||
}
|
||||
|
||||
/*
|
||||
* Encode an item, taking care of IMPLICIT tagging (if any). This function
|
||||
* performs the normal item handling: it can be used in external types.
|
||||
*/
|
||||
|
||||
int ASN1_item_ex_i2d(ASN1_VALUE **pval, unsigned char **out,
|
||||
const ASN1_ITEM *it, int tag, int aclass)
|
||||
{
|
||||
const ASN1_TEMPLATE *tt = NULL;
|
||||
unsigned char *p = NULL;
|
||||
int i, seqcontlen, seqlen, ndef = 1;
|
||||
const ASN1_COMPAT_FUNCS *cf;
|
||||
const ASN1_EXTERN_FUNCS *ef;
|
||||
const ASN1_AUX *aux = it->funcs;
|
||||
ASN1_aux_cb *asn1_cb = 0;
|
||||
|
||||
if ((it->itype != ASN1_ITYPE_PRIMITIVE) && !*pval)
|
||||
return 0;
|
||||
|
||||
if (aux && aux->asn1_cb)
|
||||
asn1_cb = aux->asn1_cb;
|
||||
|
||||
switch (it->itype) {
|
||||
|
||||
case ASN1_ITYPE_PRIMITIVE:
|
||||
if (it->templates)
|
||||
return asn1_template_ex_i2d(pval, out, it->templates,
|
||||
tag, aclass);
|
||||
return asn1_i2d_ex_primitive(pval, out, it, tag, aclass);
|
||||
break;
|
||||
|
||||
case ASN1_ITYPE_MSTRING:
|
||||
return asn1_i2d_ex_primitive(pval, out, it, -1, aclass);
|
||||
|
||||
case ASN1_ITYPE_CHOICE:
|
||||
if (asn1_cb && !asn1_cb(ASN1_OP_I2D_PRE, pval, it, NULL))
|
||||
return 0;
|
||||
i = asn1_get_choice_selector(pval, it);
|
||||
if ((i >= 0) && (i < it->tcount)) {
|
||||
ASN1_VALUE **pchval;
|
||||
const ASN1_TEMPLATE *chtt;
|
||||
chtt = it->templates + i;
|
||||
pchval = asn1_get_field_ptr(pval, chtt);
|
||||
return asn1_template_ex_i2d(pchval, out, chtt, -1, aclass);
|
||||
}
|
||||
/* Fixme: error condition if selector out of range */
|
||||
if (asn1_cb && !asn1_cb(ASN1_OP_I2D_POST, pval, it, NULL))
|
||||
return 0;
|
||||
break;
|
||||
|
||||
case ASN1_ITYPE_EXTERN:
|
||||
/* If new style i2d it does all the work */
|
||||
ef = it->funcs;
|
||||
return ef->asn1_ex_i2d(pval, out, it, tag, aclass);
|
||||
|
||||
case ASN1_ITYPE_COMPAT:
|
||||
/* old style hackery... */
|
||||
cf = it->funcs;
|
||||
if (out)
|
||||
p = *out;
|
||||
i = cf->asn1_i2d(*pval, out);
|
||||
/*
|
||||
* Fixup for IMPLICIT tag: note this messes up for tags > 30, but so
|
||||
* did the old code. Tags > 30 are very rare anyway.
|
||||
*/
|
||||
if (out && (tag != -1))
|
||||
*p = aclass | tag | (*p & V_ASN1_CONSTRUCTED);
|
||||
return i;
|
||||
|
||||
case ASN1_ITYPE_NDEF_SEQUENCE:
|
||||
/* Use indefinite length constructed if requested */
|
||||
if (aclass & ASN1_TFLG_NDEF)
|
||||
ndef = 2;
|
||||
OPENSSL_FALLTHROUGH;
|
||||
|
||||
case ASN1_ITYPE_SEQUENCE:
|
||||
i = asn1_enc_restore(&seqcontlen, out, pval, it);
|
||||
/* An error occurred */
|
||||
if (i < 0)
|
||||
return 0;
|
||||
/* We have a valid cached encoding... */
|
||||
if (i > 0)
|
||||
return seqcontlen;
|
||||
/* Otherwise carry on */
|
||||
seqcontlen = 0;
|
||||
/* If no IMPLICIT tagging set to SEQUENCE, UNIVERSAL */
|
||||
if (tag == -1) {
|
||||
tag = V_ASN1_SEQUENCE;
|
||||
/* Retain any other flags in aclass */
|
||||
aclass = (aclass & ~ASN1_TFLG_TAG_CLASS)
|
||||
| V_ASN1_UNIVERSAL;
|
||||
}
|
||||
if (asn1_cb && !asn1_cb(ASN1_OP_I2D_PRE, pval, it, NULL))
|
||||
return 0;
|
||||
/* First work out sequence content length */
|
||||
for (i = 0, tt = it->templates; i < it->tcount; tt++, i++) {
|
||||
const ASN1_TEMPLATE *seqtt;
|
||||
ASN1_VALUE **pseqval;
|
||||
int tmplen;
|
||||
seqtt = asn1_do_adb(pval, tt, 1);
|
||||
if (!seqtt)
|
||||
return 0;
|
||||
pseqval = asn1_get_field_ptr(pval, seqtt);
|
||||
tmplen = asn1_template_ex_i2d(pseqval, NULL, seqtt, -1, aclass);
|
||||
if (tmplen == -1 || (tmplen > INT_MAX - seqcontlen))
|
||||
return -1;
|
||||
seqcontlen += tmplen;
|
||||
}
|
||||
|
||||
seqlen = ASN1_object_size(ndef, seqcontlen, tag);
|
||||
if (!out || seqlen == -1)
|
||||
return seqlen;
|
||||
/* Output SEQUENCE header */
|
||||
ASN1_put_object(out, ndef, seqcontlen, tag, aclass);
|
||||
for (i = 0, tt = it->templates; i < it->tcount; tt++, i++) {
|
||||
const ASN1_TEMPLATE *seqtt;
|
||||
ASN1_VALUE **pseqval;
|
||||
seqtt = asn1_do_adb(pval, tt, 1);
|
||||
if (!seqtt)
|
||||
return 0;
|
||||
pseqval = asn1_get_field_ptr(pval, seqtt);
|
||||
/* FIXME: check for errors in enhanced version */
|
||||
asn1_template_ex_i2d(pseqval, out, seqtt, -1, aclass);
|
||||
}
|
||||
if (ndef == 2)
|
||||
ASN1_put_eoc(out);
|
||||
if (asn1_cb && !asn1_cb(ASN1_OP_I2D_POST, pval, it, NULL))
|
||||
return 0;
|
||||
return seqlen;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int asn1_template_ex_i2d(ASN1_VALUE **pval, unsigned char **out,
|
||||
const ASN1_TEMPLATE *tt, int tag, int iclass)
|
||||
{
|
||||
int i, ret, flags, ttag, tclass, ndef;
|
||||
size_t j;
|
||||
flags = tt->flags;
|
||||
/*
|
||||
* Work out tag and class to use: tagging may come either from the
|
||||
* template or the arguments, not both because this would create
|
||||
* ambiguity. Additionally the iclass argument may contain some
|
||||
* additional flags which should be noted and passed down to other
|
||||
* levels.
|
||||
*/
|
||||
if (flags & ASN1_TFLG_TAG_MASK) {
|
||||
/* Error if argument and template tagging */
|
||||
if (tag != -1)
|
||||
/* FIXME: error code here */
|
||||
return -1;
|
||||
/* Get tagging from template */
|
||||
ttag = tt->tag;
|
||||
tclass = flags & ASN1_TFLG_TAG_CLASS;
|
||||
} else if (tag != -1) {
|
||||
/* No template tagging, get from arguments */
|
||||
ttag = tag;
|
||||
tclass = iclass & ASN1_TFLG_TAG_CLASS;
|
||||
} else {
|
||||
ttag = -1;
|
||||
tclass = 0;
|
||||
}
|
||||
/*
|
||||
* Remove any class mask from iflag.
|
||||
*/
|
||||
iclass &= ~ASN1_TFLG_TAG_CLASS;
|
||||
|
||||
/*
|
||||
* At this point 'ttag' contains the outer tag to use, 'tclass' is the
|
||||
* class and iclass is any flags passed to this function.
|
||||
*/
|
||||
|
||||
/* if template and arguments require ndef, use it */
|
||||
if ((flags & ASN1_TFLG_NDEF) && (iclass & ASN1_TFLG_NDEF))
|
||||
ndef = 2;
|
||||
else
|
||||
ndef = 1;
|
||||
|
||||
if (flags & ASN1_TFLG_SK_MASK) {
|
||||
/* SET OF, SEQUENCE OF */
|
||||
STACK_OF(ASN1_VALUE) *sk = (STACK_OF(ASN1_VALUE) *)*pval;
|
||||
int isset, sktag, skaclass;
|
||||
int skcontlen, sklen;
|
||||
ASN1_VALUE *skitem;
|
||||
|
||||
if (!*pval)
|
||||
return 0;
|
||||
|
||||
if (flags & ASN1_TFLG_SET_OF) {
|
||||
isset = 1;
|
||||
/* 2 means we reorder */
|
||||
if (flags & ASN1_TFLG_SEQUENCE_OF)
|
||||
isset = 2;
|
||||
} else
|
||||
isset = 0;
|
||||
|
||||
/*
|
||||
* Work out inner tag value: if EXPLICIT or no tagging use underlying
|
||||
* type.
|
||||
*/
|
||||
if ((ttag != -1) && !(flags & ASN1_TFLG_EXPTAG)) {
|
||||
sktag = ttag;
|
||||
skaclass = tclass;
|
||||
} else {
|
||||
skaclass = V_ASN1_UNIVERSAL;
|
||||
if (isset)
|
||||
sktag = V_ASN1_SET;
|
||||
else
|
||||
sktag = V_ASN1_SEQUENCE;
|
||||
}
|
||||
|
||||
/* Determine total length of items */
|
||||
skcontlen = 0;
|
||||
for (j = 0; j < sk_ASN1_VALUE_num(sk); j++) {
|
||||
int tmplen;
|
||||
skitem = sk_ASN1_VALUE_value(sk, j);
|
||||
tmplen = ASN1_item_ex_i2d(&skitem, NULL, ASN1_ITEM_ptr(tt->item),
|
||||
-1, iclass);
|
||||
if (tmplen == -1 || (skcontlen > INT_MAX - tmplen))
|
||||
return -1;
|
||||
skcontlen += tmplen;
|
||||
}
|
||||
sklen = ASN1_object_size(ndef, skcontlen, sktag);
|
||||
if (sklen == -1)
|
||||
return -1;
|
||||
/* If EXPLICIT need length of surrounding tag */
|
||||
if (flags & ASN1_TFLG_EXPTAG)
|
||||
ret = ASN1_object_size(ndef, sklen, ttag);
|
||||
else
|
||||
ret = sklen;
|
||||
|
||||
if (!out || ret == -1)
|
||||
return ret;
|
||||
|
||||
/* Now encode this lot... */
|
||||
/* EXPLICIT tag */
|
||||
if (flags & ASN1_TFLG_EXPTAG)
|
||||
ASN1_put_object(out, ndef, sklen, ttag, tclass);
|
||||
/* SET or SEQUENCE and IMPLICIT tag */
|
||||
ASN1_put_object(out, ndef, skcontlen, sktag, skaclass);
|
||||
/* And the stuff itself */
|
||||
asn1_set_seq_out(sk, out, skcontlen, ASN1_ITEM_ptr(tt->item),
|
||||
isset, iclass);
|
||||
if (ndef == 2) {
|
||||
ASN1_put_eoc(out);
|
||||
if (flags & ASN1_TFLG_EXPTAG)
|
||||
ASN1_put_eoc(out);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (flags & ASN1_TFLG_EXPTAG) {
|
||||
/* EXPLICIT tagging */
|
||||
/* Find length of tagged item */
|
||||
i = ASN1_item_ex_i2d(pval, NULL, ASN1_ITEM_ptr(tt->item), -1, iclass);
|
||||
if (!i)
|
||||
return 0;
|
||||
/* Find length of EXPLICIT tag */
|
||||
ret = ASN1_object_size(ndef, i, ttag);
|
||||
if (out && ret != -1) {
|
||||
/* Output tag and item */
|
||||
ASN1_put_object(out, ndef, i, ttag, tclass);
|
||||
ASN1_item_ex_i2d(pval, out, ASN1_ITEM_ptr(tt->item), -1, iclass);
|
||||
if (ndef == 2)
|
||||
ASN1_put_eoc(out);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Either normal or IMPLICIT tagging: combine class and flags */
|
||||
return ASN1_item_ex_i2d(pval, out, ASN1_ITEM_ptr(tt->item),
|
||||
ttag, tclass | iclass);
|
||||
|
||||
}
|
||||
|
||||
/* Temporary structure used to hold DER encoding of items for SET OF */
|
||||
|
||||
typedef struct {
|
||||
unsigned char *data;
|
||||
int length;
|
||||
ASN1_VALUE *field;
|
||||
} DER_ENC;
|
||||
|
||||
static int der_cmp(const void *a, const void *b)
|
||||
{
|
||||
const DER_ENC *d1 = a, *d2 = b;
|
||||
int cmplen, i;
|
||||
cmplen = (d1->length < d2->length) ? d1->length : d2->length;
|
||||
i = OPENSSL_memcmp(d1->data, d2->data, cmplen);
|
||||
if (i)
|
||||
return i;
|
||||
return d1->length - d2->length;
|
||||
}
|
||||
|
||||
/* Output the content octets of SET OF or SEQUENCE OF */
|
||||
|
||||
static int asn1_set_seq_out(STACK_OF(ASN1_VALUE) *sk, unsigned char **out,
|
||||
int skcontlen, const ASN1_ITEM *item,
|
||||
int do_sort, int iclass)
|
||||
{
|
||||
size_t i;
|
||||
ASN1_VALUE *skitem;
|
||||
unsigned char *tmpdat = NULL, *p = NULL;
|
||||
DER_ENC *derlst = NULL, *tder;
|
||||
if (do_sort) {
|
||||
/* Don't need to sort less than 2 items */
|
||||
if (sk_ASN1_VALUE_num(sk) < 2)
|
||||
do_sort = 0;
|
||||
else {
|
||||
derlst = OPENSSL_malloc(sk_ASN1_VALUE_num(sk)
|
||||
* sizeof(*derlst));
|
||||
if (!derlst)
|
||||
return 0;
|
||||
tmpdat = OPENSSL_malloc(skcontlen);
|
||||
if (!tmpdat) {
|
||||
OPENSSL_free(derlst);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* If not sorting just output each item */
|
||||
if (!do_sort) {
|
||||
for (i = 0; i < sk_ASN1_VALUE_num(sk); i++) {
|
||||
skitem = sk_ASN1_VALUE_value(sk, i);
|
||||
ASN1_item_ex_i2d(&skitem, out, item, -1, iclass);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
p = tmpdat;
|
||||
|
||||
/* Doing sort: build up a list of each member's DER encoding */
|
||||
for (i = 0, tder = derlst; i < sk_ASN1_VALUE_num(sk); i++, tder++) {
|
||||
skitem = sk_ASN1_VALUE_value(sk, i);
|
||||
tder->data = p;
|
||||
tder->length = ASN1_item_ex_i2d(&skitem, &p, item, -1, iclass);
|
||||
tder->field = skitem;
|
||||
}
|
||||
|
||||
/* Now sort them */
|
||||
qsort(derlst, sk_ASN1_VALUE_num(sk), sizeof(*derlst), der_cmp);
|
||||
/* Output sorted DER encoding */
|
||||
p = *out;
|
||||
for (i = 0, tder = derlst; i < sk_ASN1_VALUE_num(sk); i++, tder++) {
|
||||
OPENSSL_memcpy(p, tder->data, tder->length);
|
||||
p += tder->length;
|
||||
}
|
||||
*out = p;
|
||||
/* If do_sort is 2 then reorder the STACK */
|
||||
if (do_sort == 2) {
|
||||
for (i = 0, tder = derlst; i < sk_ASN1_VALUE_num(sk); i++, tder++)
|
||||
(void)sk_ASN1_VALUE_set(sk, i, tder->field);
|
||||
}
|
||||
OPENSSL_free(derlst);
|
||||
OPENSSL_free(tmpdat);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int asn1_i2d_ex_primitive(ASN1_VALUE **pval, unsigned char **out,
|
||||
const ASN1_ITEM *it, int tag, int aclass)
|
||||
{
|
||||
int len;
|
||||
int utype;
|
||||
int usetag;
|
||||
int ndef = 0;
|
||||
|
||||
utype = it->utype;
|
||||
|
||||
/*
|
||||
* Get length of content octets and maybe find out the underlying type.
|
||||
*/
|
||||
|
||||
len = asn1_ex_i2c(pval, NULL, &utype, it);
|
||||
|
||||
/*
|
||||
* If SEQUENCE, SET or OTHER then header is included in pseudo content
|
||||
* octets so don't include tag+length. We need to check here because the
|
||||
* call to asn1_ex_i2c() could change utype.
|
||||
*/
|
||||
if ((utype == V_ASN1_SEQUENCE) || (utype == V_ASN1_SET) ||
|
||||
(utype == V_ASN1_OTHER))
|
||||
usetag = 0;
|
||||
else
|
||||
usetag = 1;
|
||||
|
||||
/* -1 means omit type */
|
||||
|
||||
if (len == -1)
|
||||
return 0;
|
||||
|
||||
/* -2 return is special meaning use ndef */
|
||||
if (len == -2) {
|
||||
ndef = 2;
|
||||
len = 0;
|
||||
}
|
||||
|
||||
/* If not implicitly tagged get tag from underlying type */
|
||||
if (tag == -1)
|
||||
tag = utype;
|
||||
|
||||
/* Output tag+length followed by content octets */
|
||||
if (out) {
|
||||
if (usetag)
|
||||
ASN1_put_object(out, ndef, len, tag, aclass);
|
||||
asn1_ex_i2c(pval, *out, &utype, it);
|
||||
if (ndef)
|
||||
ASN1_put_eoc(out);
|
||||
else
|
||||
*out += len;
|
||||
}
|
||||
|
||||
if (usetag)
|
||||
return ASN1_object_size(ndef, len, tag);
|
||||
return len;
|
||||
}
|
||||
|
||||
/* Produce content octets from a structure */
|
||||
|
||||
int asn1_ex_i2c(ASN1_VALUE **pval, unsigned char *cout, int *putype,
|
||||
const ASN1_ITEM *it)
|
||||
{
|
||||
ASN1_BOOLEAN *tbool = NULL;
|
||||
ASN1_STRING *strtmp;
|
||||
ASN1_OBJECT *otmp;
|
||||
int utype;
|
||||
const unsigned char *cont;
|
||||
unsigned char c;
|
||||
int len;
|
||||
const ASN1_PRIMITIVE_FUNCS *pf;
|
||||
pf = it->funcs;
|
||||
if (pf && pf->prim_i2c)
|
||||
return pf->prim_i2c(pval, cout, putype, it);
|
||||
|
||||
/* Should type be omitted? */
|
||||
if ((it->itype != ASN1_ITYPE_PRIMITIVE)
|
||||
|| (it->utype != V_ASN1_BOOLEAN)) {
|
||||
if (!*pval)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (it->itype == ASN1_ITYPE_MSTRING) {
|
||||
/* If MSTRING type set the underlying type */
|
||||
strtmp = (ASN1_STRING *)*pval;
|
||||
utype = strtmp->type;
|
||||
*putype = utype;
|
||||
} else if (it->utype == V_ASN1_ANY) {
|
||||
/* If ANY set type and pointer to value */
|
||||
ASN1_TYPE *typ;
|
||||
typ = (ASN1_TYPE *)*pval;
|
||||
utype = typ->type;
|
||||
*putype = utype;
|
||||
pval = &typ->value.asn1_value;
|
||||
} else
|
||||
utype = *putype;
|
||||
|
||||
switch (utype) {
|
||||
case V_ASN1_OBJECT:
|
||||
otmp = (ASN1_OBJECT *)*pval;
|
||||
cont = otmp->data;
|
||||
len = otmp->length;
|
||||
if (cont == NULL || len == 0)
|
||||
return -1;
|
||||
break;
|
||||
|
||||
case V_ASN1_NULL:
|
||||
cont = NULL;
|
||||
len = 0;
|
||||
break;
|
||||
|
||||
case V_ASN1_BOOLEAN:
|
||||
tbool = (ASN1_BOOLEAN *)pval;
|
||||
if (*tbool == -1)
|
||||
return -1;
|
||||
if (it->utype != V_ASN1_ANY) {
|
||||
/*
|
||||
* Default handling if value == size field then omit
|
||||
*/
|
||||
if (*tbool && (it->size > 0))
|
||||
return -1;
|
||||
if (!*tbool && !it->size)
|
||||
return -1;
|
||||
}
|
||||
c = (unsigned char)*tbool;
|
||||
cont = &c;
|
||||
len = 1;
|
||||
break;
|
||||
|
||||
case V_ASN1_BIT_STRING:
|
||||
return i2c_ASN1_BIT_STRING((ASN1_BIT_STRING *)*pval,
|
||||
cout ? &cout : NULL);
|
||||
break;
|
||||
|
||||
case V_ASN1_INTEGER:
|
||||
case V_ASN1_ENUMERATED:
|
||||
/*
|
||||
* These are all have the same content format as ASN1_INTEGER
|
||||
*/
|
||||
return i2c_ASN1_INTEGER((ASN1_INTEGER *)*pval, cout ? &cout : NULL);
|
||||
break;
|
||||
|
||||
case V_ASN1_OCTET_STRING:
|
||||
case V_ASN1_NUMERICSTRING:
|
||||
case V_ASN1_PRINTABLESTRING:
|
||||
case V_ASN1_T61STRING:
|
||||
case V_ASN1_VIDEOTEXSTRING:
|
||||
case V_ASN1_IA5STRING:
|
||||
case V_ASN1_UTCTIME:
|
||||
case V_ASN1_GENERALIZEDTIME:
|
||||
case V_ASN1_GRAPHICSTRING:
|
||||
case V_ASN1_VISIBLESTRING:
|
||||
case V_ASN1_GENERALSTRING:
|
||||
case V_ASN1_UNIVERSALSTRING:
|
||||
case V_ASN1_BMPSTRING:
|
||||
case V_ASN1_UTF8STRING:
|
||||
case V_ASN1_SEQUENCE:
|
||||
case V_ASN1_SET:
|
||||
default:
|
||||
/* All based on ASN1_STRING and handled the same */
|
||||
strtmp = (ASN1_STRING *)*pval;
|
||||
/* Special handling for NDEF */
|
||||
if ((it->size == ASN1_TFLG_NDEF)
|
||||
&& (strtmp->flags & ASN1_STRING_FLAG_NDEF)) {
|
||||
if (cout) {
|
||||
strtmp->data = cout;
|
||||
strtmp->length = 0;
|
||||
}
|
||||
/* Special return code */
|
||||
return -2;
|
||||
}
|
||||
cont = strtmp->data;
|
||||
len = strtmp->length;
|
||||
|
||||
break;
|
||||
|
||||
}
|
||||
if (cout && len)
|
||||
OPENSSL_memcpy(cout, cont, len);
|
||||
return len;
|
||||
}
|
||||
@@ -0,0 +1,664 @@
|
||||
/* Copyright (C) 1995-1998 Eric Young ([email protected])
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young ([email protected]).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson ([email protected]).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young ([email protected])"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson ([email protected])"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.] */
|
||||
|
||||
#include <openssl/asn1.h>
|
||||
|
||||
#include <limits.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <openssl/asn1t.h>
|
||||
#include <openssl/mem.h>
|
||||
|
||||
#include "../internal.h"
|
||||
|
||||
|
||||
static int asn1_i2d_ex_primitive(ASN1_VALUE **pval, unsigned char **out,
|
||||
const ASN1_ITEM *it, int tag, int aclass);
|
||||
static int asn1_set_seq_out(STACK_OF(ASN1_VALUE) *sk, unsigned char **out,
|
||||
int skcontlen, const ASN1_ITEM *item,
|
||||
int do_sort, int iclass);
|
||||
static int asn1_template_ex_i2d(ASN1_VALUE **pval, unsigned char **out,
|
||||
const ASN1_TEMPLATE *tt, int tag, int aclass);
|
||||
static int asn1_item_flags_i2d(ASN1_VALUE *val, unsigned char **out,
|
||||
const ASN1_ITEM *it, int flags);
|
||||
|
||||
/*
|
||||
* Top level i2d equivalents: the 'ndef' variant instructs the encoder to use
|
||||
* indefinite length constructed encoding, where appropriate
|
||||
*/
|
||||
|
||||
int ASN1_item_ndef_i2d(ASN1_VALUE *val, unsigned char **out,
|
||||
const ASN1_ITEM *it)
|
||||
{
|
||||
return asn1_item_flags_i2d(val, out, it, ASN1_TFLG_NDEF);
|
||||
}
|
||||
|
||||
int ASN1_item_i2d(ASN1_VALUE *val, unsigned char **out, const ASN1_ITEM *it)
|
||||
{
|
||||
return asn1_item_flags_i2d(val, out, it, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Encode an ASN1 item, this is use by the standard 'i2d' function. 'out'
|
||||
* points to a buffer to output the data to. The new i2d has one additional
|
||||
* feature. If the output buffer is NULL (i.e. *out == NULL) then a buffer is
|
||||
* allocated and populated with the encoding.
|
||||
*/
|
||||
|
||||
static int asn1_item_flags_i2d(ASN1_VALUE *val, unsigned char **out,
|
||||
const ASN1_ITEM *it, int flags)
|
||||
{
|
||||
if (out && !*out) {
|
||||
unsigned char *p, *buf;
|
||||
int len;
|
||||
len = ASN1_item_ex_i2d(&val, NULL, it, -1, flags);
|
||||
if (len <= 0)
|
||||
return len;
|
||||
buf = OPENSSL_malloc(len);
|
||||
if (!buf)
|
||||
return -1;
|
||||
p = buf;
|
||||
ASN1_item_ex_i2d(&val, &p, it, -1, flags);
|
||||
*out = buf;
|
||||
return len;
|
||||
}
|
||||
|
||||
return ASN1_item_ex_i2d(&val, out, it, -1, flags);
|
||||
}
|
||||
|
||||
/*
|
||||
* Encode an item, taking care of IMPLICIT tagging (if any). This function
|
||||
* performs the normal item handling: it can be used in external types.
|
||||
*/
|
||||
|
||||
int ASN1_item_ex_i2d(ASN1_VALUE **pval, unsigned char **out,
|
||||
const ASN1_ITEM *it, int tag, int aclass)
|
||||
{
|
||||
const ASN1_TEMPLATE *tt = NULL;
|
||||
unsigned char *p = NULL;
|
||||
int i, seqcontlen, seqlen, ndef = 1;
|
||||
const ASN1_COMPAT_FUNCS *cf;
|
||||
const ASN1_EXTERN_FUNCS *ef;
|
||||
const ASN1_AUX *aux = it->funcs;
|
||||
ASN1_aux_cb *asn1_cb = 0;
|
||||
|
||||
if ((it->itype != ASN1_ITYPE_PRIMITIVE) && !*pval)
|
||||
return 0;
|
||||
|
||||
if (aux && aux->asn1_cb)
|
||||
asn1_cb = aux->asn1_cb;
|
||||
|
||||
switch (it->itype) {
|
||||
|
||||
case ASN1_ITYPE_PRIMITIVE:
|
||||
if (it->templates)
|
||||
return asn1_template_ex_i2d(pval, out, it->templates,
|
||||
tag, aclass);
|
||||
return asn1_i2d_ex_primitive(pval, out, it, tag, aclass);
|
||||
break;
|
||||
|
||||
case ASN1_ITYPE_MSTRING:
|
||||
return asn1_i2d_ex_primitive(pval, out, it, -1, aclass);
|
||||
|
||||
case ASN1_ITYPE_CHOICE:
|
||||
if (asn1_cb && !asn1_cb(ASN1_OP_I2D_PRE, pval, it, NULL))
|
||||
return 0;
|
||||
i = asn1_get_choice_selector(pval, it);
|
||||
if ((i >= 0) && (i < it->tcount)) {
|
||||
ASN1_VALUE **pchval;
|
||||
const ASN1_TEMPLATE *chtt;
|
||||
chtt = it->templates + i;
|
||||
pchval = asn1_get_field_ptr(pval, chtt);
|
||||
return asn1_template_ex_i2d(pchval, out, chtt, -1, aclass);
|
||||
}
|
||||
/* Fixme: error condition if selector out of range */
|
||||
if (asn1_cb && !asn1_cb(ASN1_OP_I2D_POST, pval, it, NULL))
|
||||
return 0;
|
||||
break;
|
||||
|
||||
case ASN1_ITYPE_EXTERN:
|
||||
/* If new style i2d it does all the work */
|
||||
ef = it->funcs;
|
||||
return ef->asn1_ex_i2d(pval, out, it, tag, aclass);
|
||||
|
||||
case ASN1_ITYPE_COMPAT:
|
||||
/* old style hackery... */
|
||||
cf = it->funcs;
|
||||
if (out)
|
||||
p = *out;
|
||||
i = cf->asn1_i2d(*pval, out);
|
||||
/*
|
||||
* Fixup for IMPLICIT tag: note this messes up for tags > 30, but so
|
||||
* did the old code. Tags > 30 are very rare anyway.
|
||||
*/
|
||||
if (out && (tag != -1))
|
||||
*p = aclass | tag | (*p & V_ASN1_CONSTRUCTED);
|
||||
return i;
|
||||
|
||||
case ASN1_ITYPE_NDEF_SEQUENCE:
|
||||
/* Use indefinite length constructed if requested */
|
||||
if (aclass & ASN1_TFLG_NDEF)
|
||||
ndef = 2;
|
||||
OPENSSL_FALLTHROUGH;
|
||||
|
||||
case ASN1_ITYPE_SEQUENCE:
|
||||
i = asn1_enc_restore(&seqcontlen, out, pval, it);
|
||||
/* An error occurred */
|
||||
if (i < 0)
|
||||
return 0;
|
||||
/* We have a valid cached encoding... */
|
||||
if (i > 0)
|
||||
return seqcontlen;
|
||||
/* Otherwise carry on */
|
||||
seqcontlen = 0;
|
||||
/* If no IMPLICIT tagging set to SEQUENCE, UNIVERSAL */
|
||||
if (tag == -1) {
|
||||
tag = V_ASN1_SEQUENCE;
|
||||
/* Retain any other flags in aclass */
|
||||
aclass = (aclass & ~ASN1_TFLG_TAG_CLASS)
|
||||
| V_ASN1_UNIVERSAL;
|
||||
}
|
||||
if (asn1_cb && !asn1_cb(ASN1_OP_I2D_PRE, pval, it, NULL))
|
||||
return 0;
|
||||
/* First work out sequence content length */
|
||||
for (i = 0, tt = it->templates; i < it->tcount; tt++, i++) {
|
||||
const ASN1_TEMPLATE *seqtt;
|
||||
ASN1_VALUE **pseqval;
|
||||
int tmplen;
|
||||
seqtt = asn1_do_adb(pval, tt, 1);
|
||||
if (!seqtt)
|
||||
return 0;
|
||||
pseqval = asn1_get_field_ptr(pval, seqtt);
|
||||
tmplen = asn1_template_ex_i2d(pseqval, NULL, seqtt, -1, aclass);
|
||||
if (tmplen == -1 || (tmplen > INT_MAX - seqcontlen))
|
||||
return -1;
|
||||
seqcontlen += tmplen;
|
||||
}
|
||||
|
||||
seqlen = ASN1_object_size(ndef, seqcontlen, tag);
|
||||
if (!out || seqlen == -1)
|
||||
return seqlen;
|
||||
/* Output SEQUENCE header */
|
||||
ASN1_put_object(out, ndef, seqcontlen, tag, aclass);
|
||||
for (i = 0, tt = it->templates; i < it->tcount; tt++, i++) {
|
||||
const ASN1_TEMPLATE *seqtt;
|
||||
ASN1_VALUE **pseqval;
|
||||
seqtt = asn1_do_adb(pval, tt, 1);
|
||||
if (!seqtt)
|
||||
return 0;
|
||||
pseqval = asn1_get_field_ptr(pval, seqtt);
|
||||
/* FIXME: check for errors in enhanced version */
|
||||
asn1_template_ex_i2d(pseqval, out, seqtt, -1, aclass);
|
||||
}
|
||||
if (ndef == 2)
|
||||
ASN1_put_eoc(out);
|
||||
if (asn1_cb && !asn1_cb(ASN1_OP_I2D_POST, pval, it, NULL))
|
||||
return 0;
|
||||
return seqlen;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int asn1_template_ex_i2d(ASN1_VALUE **pval, unsigned char **out,
|
||||
const ASN1_TEMPLATE *tt, int tag, int iclass)
|
||||
{
|
||||
int i, ret, flags, ttag, tclass, ndef;
|
||||
size_t j;
|
||||
flags = tt->flags;
|
||||
/*
|
||||
* Work out tag and class to use: tagging may come either from the
|
||||
* template or the arguments, not both because this would create
|
||||
* ambiguity. Additionally the iclass argument may contain some
|
||||
* additional flags which should be noted and passed down to other
|
||||
* levels.
|
||||
*/
|
||||
if (flags & ASN1_TFLG_TAG_MASK) {
|
||||
/* Error if argument and template tagging */
|
||||
if (tag != -1)
|
||||
/* FIXME: error code here */
|
||||
return -1;
|
||||
/* Get tagging from template */
|
||||
ttag = tt->tag;
|
||||
tclass = flags & ASN1_TFLG_TAG_CLASS;
|
||||
} else if (tag != -1) {
|
||||
/* No template tagging, get from arguments */
|
||||
ttag = tag;
|
||||
tclass = iclass & ASN1_TFLG_TAG_CLASS;
|
||||
} else {
|
||||
ttag = -1;
|
||||
tclass = 0;
|
||||
}
|
||||
/*
|
||||
* Remove any class mask from iflag.
|
||||
*/
|
||||
iclass &= ~ASN1_TFLG_TAG_CLASS;
|
||||
|
||||
/*
|
||||
* At this point 'ttag' contains the outer tag to use, 'tclass' is the
|
||||
* class and iclass is any flags passed to this function.
|
||||
*/
|
||||
|
||||
/* if template and arguments require ndef, use it */
|
||||
if ((flags & ASN1_TFLG_NDEF) && (iclass & ASN1_TFLG_NDEF))
|
||||
ndef = 2;
|
||||
else
|
||||
ndef = 1;
|
||||
|
||||
if (flags & ASN1_TFLG_SK_MASK) {
|
||||
/* SET OF, SEQUENCE OF */
|
||||
STACK_OF(ASN1_VALUE) *sk = (STACK_OF(ASN1_VALUE) *)*pval;
|
||||
int isset, sktag, skaclass;
|
||||
int skcontlen, sklen;
|
||||
ASN1_VALUE *skitem;
|
||||
|
||||
if (!*pval)
|
||||
return 0;
|
||||
|
||||
if (flags & ASN1_TFLG_SET_OF) {
|
||||
isset = 1;
|
||||
/* 2 means we reorder */
|
||||
if (flags & ASN1_TFLG_SEQUENCE_OF)
|
||||
isset = 2;
|
||||
} else
|
||||
isset = 0;
|
||||
|
||||
/*
|
||||
* Work out inner tag value: if EXPLICIT or no tagging use underlying
|
||||
* type.
|
||||
*/
|
||||
if ((ttag != -1) && !(flags & ASN1_TFLG_EXPTAG)) {
|
||||
sktag = ttag;
|
||||
skaclass = tclass;
|
||||
} else {
|
||||
skaclass = V_ASN1_UNIVERSAL;
|
||||
if (isset)
|
||||
sktag = V_ASN1_SET;
|
||||
else
|
||||
sktag = V_ASN1_SEQUENCE;
|
||||
}
|
||||
|
||||
/* Determine total length of items */
|
||||
skcontlen = 0;
|
||||
for (j = 0; j < sk_ASN1_VALUE_num(sk); j++) {
|
||||
int tmplen;
|
||||
skitem = sk_ASN1_VALUE_value(sk, j);
|
||||
tmplen = ASN1_item_ex_i2d(&skitem, NULL, ASN1_ITEM_ptr(tt->item),
|
||||
-1, iclass);
|
||||
if (tmplen == -1 || (skcontlen > INT_MAX - tmplen))
|
||||
return -1;
|
||||
skcontlen += tmplen;
|
||||
}
|
||||
sklen = ASN1_object_size(ndef, skcontlen, sktag);
|
||||
if (sklen == -1)
|
||||
return -1;
|
||||
/* If EXPLICIT need length of surrounding tag */
|
||||
if (flags & ASN1_TFLG_EXPTAG)
|
||||
ret = ASN1_object_size(ndef, sklen, ttag);
|
||||
else
|
||||
ret = sklen;
|
||||
|
||||
if (!out || ret == -1)
|
||||
return ret;
|
||||
|
||||
/* Now encode this lot... */
|
||||
/* EXPLICIT tag */
|
||||
if (flags & ASN1_TFLG_EXPTAG)
|
||||
ASN1_put_object(out, ndef, sklen, ttag, tclass);
|
||||
/* SET or SEQUENCE and IMPLICIT tag */
|
||||
ASN1_put_object(out, ndef, skcontlen, sktag, skaclass);
|
||||
/* And the stuff itself */
|
||||
asn1_set_seq_out(sk, out, skcontlen, ASN1_ITEM_ptr(tt->item),
|
||||
isset, iclass);
|
||||
if (ndef == 2) {
|
||||
ASN1_put_eoc(out);
|
||||
if (flags & ASN1_TFLG_EXPTAG)
|
||||
ASN1_put_eoc(out);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (flags & ASN1_TFLG_EXPTAG) {
|
||||
/* EXPLICIT tagging */
|
||||
/* Find length of tagged item */
|
||||
i = ASN1_item_ex_i2d(pval, NULL, ASN1_ITEM_ptr(tt->item), -1, iclass);
|
||||
if (!i)
|
||||
return 0;
|
||||
/* Find length of EXPLICIT tag */
|
||||
ret = ASN1_object_size(ndef, i, ttag);
|
||||
if (out && ret != -1) {
|
||||
/* Output tag and item */
|
||||
ASN1_put_object(out, ndef, i, ttag, tclass);
|
||||
ASN1_item_ex_i2d(pval, out, ASN1_ITEM_ptr(tt->item), -1, iclass);
|
||||
if (ndef == 2)
|
||||
ASN1_put_eoc(out);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Either normal or IMPLICIT tagging: combine class and flags */
|
||||
return ASN1_item_ex_i2d(pval, out, ASN1_ITEM_ptr(tt->item),
|
||||
ttag, tclass | iclass);
|
||||
|
||||
}
|
||||
|
||||
/* Temporary structure used to hold DER encoding of items for SET OF */
|
||||
|
||||
typedef struct {
|
||||
unsigned char *data;
|
||||
int length;
|
||||
ASN1_VALUE *field;
|
||||
} DER_ENC;
|
||||
|
||||
static int der_cmp(const void *a, const void *b)
|
||||
{
|
||||
const DER_ENC *d1 = a, *d2 = b;
|
||||
int cmplen, i;
|
||||
cmplen = (d1->length < d2->length) ? d1->length : d2->length;
|
||||
i = OPENSSL_memcmp(d1->data, d2->data, cmplen);
|
||||
if (i)
|
||||
return i;
|
||||
return d1->length - d2->length;
|
||||
}
|
||||
|
||||
/* Output the content octets of SET OF or SEQUENCE OF */
|
||||
|
||||
static int asn1_set_seq_out(STACK_OF(ASN1_VALUE) *sk, unsigned char **out,
|
||||
int skcontlen, const ASN1_ITEM *item,
|
||||
int do_sort, int iclass)
|
||||
{
|
||||
size_t i;
|
||||
ASN1_VALUE *skitem;
|
||||
unsigned char *tmpdat = NULL, *p = NULL;
|
||||
DER_ENC *derlst = NULL, *tder;
|
||||
if (do_sort) {
|
||||
/* Don't need to sort less than 2 items */
|
||||
if (sk_ASN1_VALUE_num(sk) < 2)
|
||||
do_sort = 0;
|
||||
else {
|
||||
derlst = OPENSSL_malloc(sk_ASN1_VALUE_num(sk)
|
||||
* sizeof(*derlst));
|
||||
if (!derlst)
|
||||
return 0;
|
||||
tmpdat = OPENSSL_malloc(skcontlen);
|
||||
if (!tmpdat) {
|
||||
OPENSSL_free(derlst);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* If not sorting just output each item */
|
||||
if (!do_sort) {
|
||||
for (i = 0; i < sk_ASN1_VALUE_num(sk); i++) {
|
||||
skitem = sk_ASN1_VALUE_value(sk, i);
|
||||
ASN1_item_ex_i2d(&skitem, out, item, -1, iclass);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
p = tmpdat;
|
||||
|
||||
/* Doing sort: build up a list of each member's DER encoding */
|
||||
for (i = 0, tder = derlst; i < sk_ASN1_VALUE_num(sk); i++, tder++) {
|
||||
skitem = sk_ASN1_VALUE_value(sk, i);
|
||||
tder->data = p;
|
||||
tder->length = ASN1_item_ex_i2d(&skitem, &p, item, -1, iclass);
|
||||
tder->field = skitem;
|
||||
}
|
||||
|
||||
/* Now sort them */
|
||||
qsort(derlst, sk_ASN1_VALUE_num(sk), sizeof(*derlst), der_cmp);
|
||||
/* Output sorted DER encoding */
|
||||
p = *out;
|
||||
for (i = 0, tder = derlst; i < sk_ASN1_VALUE_num(sk); i++, tder++) {
|
||||
OPENSSL_memcpy(p, tder->data, tder->length);
|
||||
p += tder->length;
|
||||
}
|
||||
*out = p;
|
||||
/* If do_sort is 2 then reorder the STACK */
|
||||
if (do_sort == 2) {
|
||||
for (i = 0, tder = derlst; i < sk_ASN1_VALUE_num(sk); i++, tder++)
|
||||
(void)sk_ASN1_VALUE_set(sk, i, tder->field);
|
||||
}
|
||||
OPENSSL_free(derlst);
|
||||
OPENSSL_free(tmpdat);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int asn1_i2d_ex_primitive(ASN1_VALUE **pval, unsigned char **out,
|
||||
const ASN1_ITEM *it, int tag, int aclass)
|
||||
{
|
||||
int len;
|
||||
int utype;
|
||||
int usetag;
|
||||
int ndef = 0;
|
||||
|
||||
utype = it->utype;
|
||||
|
||||
/*
|
||||
* Get length of content octets and maybe find out the underlying type.
|
||||
*/
|
||||
|
||||
len = asn1_ex_i2c(pval, NULL, &utype, it);
|
||||
|
||||
/*
|
||||
* If SEQUENCE, SET or OTHER then header is included in pseudo content
|
||||
* octets so don't include tag+length. We need to check here because the
|
||||
* call to asn1_ex_i2c() could change utype.
|
||||
*/
|
||||
if ((utype == V_ASN1_SEQUENCE) || (utype == V_ASN1_SET) ||
|
||||
(utype == V_ASN1_OTHER))
|
||||
usetag = 0;
|
||||
else
|
||||
usetag = 1;
|
||||
|
||||
/* -1 means omit type */
|
||||
|
||||
if (len == -1)
|
||||
return 0;
|
||||
|
||||
/* -2 return is special meaning use ndef */
|
||||
if (len == -2) {
|
||||
ndef = 2;
|
||||
len = 0;
|
||||
}
|
||||
|
||||
/* If not implicitly tagged get tag from underlying type */
|
||||
if (tag == -1)
|
||||
tag = utype;
|
||||
|
||||
/* Output tag+length followed by content octets */
|
||||
if (out) {
|
||||
if (usetag)
|
||||
ASN1_put_object(out, ndef, len, tag, aclass);
|
||||
asn1_ex_i2c(pval, *out, &utype, it);
|
||||
if (ndef)
|
||||
ASN1_put_eoc(out);
|
||||
else
|
||||
*out += len;
|
||||
}
|
||||
|
||||
if (usetag)
|
||||
return ASN1_object_size(ndef, len, tag);
|
||||
return len;
|
||||
}
|
||||
|
||||
/* Produce content octets from a structure */
|
||||
|
||||
int asn1_ex_i2c(ASN1_VALUE **pval, unsigned char *cout, int *putype,
|
||||
const ASN1_ITEM *it)
|
||||
{
|
||||
ASN1_BOOLEAN *tbool = NULL;
|
||||
ASN1_STRING *strtmp;
|
||||
ASN1_OBJECT *otmp;
|
||||
int utype;
|
||||
const unsigned char *cont;
|
||||
unsigned char c;
|
||||
int len;
|
||||
const ASN1_PRIMITIVE_FUNCS *pf;
|
||||
pf = it->funcs;
|
||||
if (pf && pf->prim_i2c)
|
||||
return pf->prim_i2c(pval, cout, putype, it);
|
||||
|
||||
/* Should type be omitted? */
|
||||
if ((it->itype != ASN1_ITYPE_PRIMITIVE)
|
||||
|| (it->utype != V_ASN1_BOOLEAN)) {
|
||||
if (!*pval)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (it->itype == ASN1_ITYPE_MSTRING) {
|
||||
/* If MSTRING type set the underlying type */
|
||||
strtmp = (ASN1_STRING *)*pval;
|
||||
utype = strtmp->type;
|
||||
*putype = utype;
|
||||
} else if (it->utype == V_ASN1_ANY) {
|
||||
/* If ANY set type and pointer to value */
|
||||
ASN1_TYPE *typ;
|
||||
typ = (ASN1_TYPE *)*pval;
|
||||
utype = typ->type;
|
||||
*putype = utype;
|
||||
pval = &typ->value.asn1_value;
|
||||
} else
|
||||
utype = *putype;
|
||||
|
||||
switch (utype) {
|
||||
case V_ASN1_OBJECT:
|
||||
otmp = (ASN1_OBJECT *)*pval;
|
||||
cont = otmp->data;
|
||||
len = otmp->length;
|
||||
if (cont == NULL || len == 0)
|
||||
return -1;
|
||||
break;
|
||||
|
||||
case V_ASN1_NULL:
|
||||
cont = NULL;
|
||||
len = 0;
|
||||
break;
|
||||
|
||||
case V_ASN1_BOOLEAN:
|
||||
tbool = (ASN1_BOOLEAN *)pval;
|
||||
if (*tbool == -1)
|
||||
return -1;
|
||||
if (it->utype != V_ASN1_ANY) {
|
||||
/*
|
||||
* Default handling if value == size field then omit
|
||||
*/
|
||||
if (*tbool && (it->size > 0))
|
||||
return -1;
|
||||
if (!*tbool && !it->size)
|
||||
return -1;
|
||||
}
|
||||
c = (unsigned char)*tbool;
|
||||
cont = &c;
|
||||
len = 1;
|
||||
break;
|
||||
|
||||
case V_ASN1_BIT_STRING:
|
||||
return i2c_ASN1_BIT_STRING((ASN1_BIT_STRING *)*pval,
|
||||
cout ? &cout : NULL);
|
||||
break;
|
||||
|
||||
case V_ASN1_INTEGER:
|
||||
case V_ASN1_ENUMERATED:
|
||||
/*
|
||||
* These are all have the same content format as ASN1_INTEGER
|
||||
*/
|
||||
return i2c_ASN1_INTEGER((ASN1_INTEGER *)*pval, cout ? &cout : NULL);
|
||||
break;
|
||||
|
||||
case V_ASN1_OCTET_STRING:
|
||||
case V_ASN1_NUMERICSTRING:
|
||||
case V_ASN1_PRINTABLESTRING:
|
||||
case V_ASN1_T61STRING:
|
||||
case V_ASN1_VIDEOTEXSTRING:
|
||||
case V_ASN1_IA5STRING:
|
||||
case V_ASN1_UTCTIME:
|
||||
case V_ASN1_GENERALIZEDTIME:
|
||||
case V_ASN1_GRAPHICSTRING:
|
||||
case V_ASN1_VISIBLESTRING:
|
||||
case V_ASN1_GENERALSTRING:
|
||||
case V_ASN1_UNIVERSALSTRING:
|
||||
case V_ASN1_BMPSTRING:
|
||||
case V_ASN1_UTF8STRING:
|
||||
case V_ASN1_SEQUENCE:
|
||||
case V_ASN1_SET:
|
||||
default:
|
||||
/* All based on ASN1_STRING and handled the same */
|
||||
strtmp = (ASN1_STRING *)*pval;
|
||||
/* Special handling for NDEF */
|
||||
if ((it->size == ASN1_TFLG_NDEF)
|
||||
&& (strtmp->flags & ASN1_STRING_FLAG_NDEF)) {
|
||||
if (cout) {
|
||||
strtmp->data = cout;
|
||||
strtmp->length = 0;
|
||||
}
|
||||
/* Special return code */
|
||||
return -2;
|
||||
}
|
||||
cont = strtmp->data;
|
||||
len = strtmp->length;
|
||||
|
||||
break;
|
||||
|
||||
}
|
||||
if (cout && len)
|
||||
OPENSSL_memcpy(cout, cont, len);
|
||||
return len;
|
||||
}
|
||||
+244
@@ -0,0 +1,244 @@
|
||||
/* Copyright (C) 1995-1998 Eric Young ([email protected])
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young ([email protected]).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson ([email protected]).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young ([email protected])"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson ([email protected])"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.] */
|
||||
|
||||
#include <openssl_grpc/asn1.h>
|
||||
|
||||
#include <openssl_grpc/asn1t.h>
|
||||
#include <openssl_grpc/mem.h>
|
||||
|
||||
#include "asn1_locl.h"
|
||||
|
||||
/* Free up an ASN1 structure */
|
||||
|
||||
void ASN1_item_free(ASN1_VALUE *val, const ASN1_ITEM *it)
|
||||
{
|
||||
asn1_item_combine_free(&val, it, 0);
|
||||
}
|
||||
|
||||
void ASN1_item_ex_free(ASN1_VALUE **pval, const ASN1_ITEM *it)
|
||||
{
|
||||
asn1_item_combine_free(pval, it, 0);
|
||||
}
|
||||
|
||||
void asn1_item_combine_free(ASN1_VALUE **pval, const ASN1_ITEM *it, int combine)
|
||||
{
|
||||
const ASN1_TEMPLATE *tt = NULL, *seqtt;
|
||||
const ASN1_EXTERN_FUNCS *ef;
|
||||
const ASN1_COMPAT_FUNCS *cf;
|
||||
const ASN1_AUX *aux = it->funcs;
|
||||
ASN1_aux_cb *asn1_cb;
|
||||
int i;
|
||||
if (!pval)
|
||||
return;
|
||||
if ((it->itype != ASN1_ITYPE_PRIMITIVE) && !*pval)
|
||||
return;
|
||||
if (aux && aux->asn1_cb)
|
||||
asn1_cb = aux->asn1_cb;
|
||||
else
|
||||
asn1_cb = 0;
|
||||
|
||||
switch (it->itype) {
|
||||
|
||||
case ASN1_ITYPE_PRIMITIVE:
|
||||
if (it->templates)
|
||||
ASN1_template_free(pval, it->templates);
|
||||
else
|
||||
ASN1_primitive_free(pval, it);
|
||||
break;
|
||||
|
||||
case ASN1_ITYPE_MSTRING:
|
||||
ASN1_primitive_free(pval, it);
|
||||
break;
|
||||
|
||||
case ASN1_ITYPE_CHOICE:
|
||||
if (asn1_cb) {
|
||||
i = asn1_cb(ASN1_OP_FREE_PRE, pval, it, NULL);
|
||||
if (i == 2)
|
||||
return;
|
||||
}
|
||||
i = asn1_get_choice_selector(pval, it);
|
||||
if ((i >= 0) && (i < it->tcount)) {
|
||||
ASN1_VALUE **pchval;
|
||||
tt = it->templates + i;
|
||||
pchval = asn1_get_field_ptr(pval, tt);
|
||||
ASN1_template_free(pchval, tt);
|
||||
}
|
||||
if (asn1_cb)
|
||||
asn1_cb(ASN1_OP_FREE_POST, pval, it, NULL);
|
||||
if (!combine) {
|
||||
OPENSSL_free(*pval);
|
||||
*pval = NULL;
|
||||
}
|
||||
break;
|
||||
|
||||
case ASN1_ITYPE_COMPAT:
|
||||
cf = it->funcs;
|
||||
if (cf && cf->asn1_free)
|
||||
cf->asn1_free(*pval);
|
||||
break;
|
||||
|
||||
case ASN1_ITYPE_EXTERN:
|
||||
ef = it->funcs;
|
||||
if (ef && ef->asn1_ex_free)
|
||||
ef->asn1_ex_free(pval, it);
|
||||
break;
|
||||
|
||||
case ASN1_ITYPE_NDEF_SEQUENCE:
|
||||
case ASN1_ITYPE_SEQUENCE:
|
||||
if (!asn1_refcount_dec_and_test_zero(pval, it))
|
||||
return;
|
||||
if (asn1_cb) {
|
||||
i = asn1_cb(ASN1_OP_FREE_PRE, pval, it, NULL);
|
||||
if (i == 2)
|
||||
return;
|
||||
}
|
||||
asn1_enc_free(pval, it);
|
||||
/*
|
||||
* If we free up as normal we will invalidate any ANY DEFINED BY
|
||||
* field and we wont be able to determine the type of the field it
|
||||
* defines. So free up in reverse order.
|
||||
*/
|
||||
tt = it->templates + it->tcount - 1;
|
||||
for (i = 0; i < it->tcount; tt--, i++) {
|
||||
ASN1_VALUE **pseqval;
|
||||
seqtt = asn1_do_adb(pval, tt, 0);
|
||||
if (!seqtt)
|
||||
continue;
|
||||
pseqval = asn1_get_field_ptr(pval, seqtt);
|
||||
ASN1_template_free(pseqval, seqtt);
|
||||
}
|
||||
if (asn1_cb)
|
||||
asn1_cb(ASN1_OP_FREE_POST, pval, it, NULL);
|
||||
if (!combine) {
|
||||
OPENSSL_free(*pval);
|
||||
*pval = NULL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void ASN1_template_free(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt)
|
||||
{
|
||||
size_t i;
|
||||
if (tt->flags & ASN1_TFLG_SK_MASK) {
|
||||
STACK_OF(ASN1_VALUE) *sk = (STACK_OF(ASN1_VALUE) *)*pval;
|
||||
for (i = 0; i < sk_ASN1_VALUE_num(sk); i++) {
|
||||
ASN1_VALUE *vtmp;
|
||||
vtmp = sk_ASN1_VALUE_value(sk, i);
|
||||
asn1_item_combine_free(&vtmp, ASN1_ITEM_ptr(tt->item), 0);
|
||||
}
|
||||
sk_ASN1_VALUE_free(sk);
|
||||
*pval = NULL;
|
||||
} else
|
||||
asn1_item_combine_free(pval, ASN1_ITEM_ptr(tt->item),
|
||||
tt->flags & ASN1_TFLG_COMBINE);
|
||||
}
|
||||
|
||||
void ASN1_primitive_free(ASN1_VALUE **pval, const ASN1_ITEM *it)
|
||||
{
|
||||
int utype;
|
||||
if (it) {
|
||||
const ASN1_PRIMITIVE_FUNCS *pf;
|
||||
pf = it->funcs;
|
||||
if (pf && pf->prim_free) {
|
||||
pf->prim_free(pval, it);
|
||||
return;
|
||||
}
|
||||
}
|
||||
/* Special case: if 'it' is NULL free contents of ASN1_TYPE */
|
||||
if (!it) {
|
||||
ASN1_TYPE *typ = (ASN1_TYPE *)*pval;
|
||||
utype = typ->type;
|
||||
pval = &typ->value.asn1_value;
|
||||
if (!*pval)
|
||||
return;
|
||||
} else if (it->itype == ASN1_ITYPE_MSTRING) {
|
||||
utype = -1;
|
||||
if (!*pval)
|
||||
return;
|
||||
} else {
|
||||
utype = it->utype;
|
||||
if ((utype != V_ASN1_BOOLEAN) && !*pval)
|
||||
return;
|
||||
}
|
||||
|
||||
switch (utype) {
|
||||
case V_ASN1_OBJECT:
|
||||
ASN1_OBJECT_free((ASN1_OBJECT *)*pval);
|
||||
break;
|
||||
|
||||
case V_ASN1_BOOLEAN:
|
||||
if (it)
|
||||
*(ASN1_BOOLEAN *)pval = it->size;
|
||||
else
|
||||
*(ASN1_BOOLEAN *)pval = -1;
|
||||
return;
|
||||
|
||||
case V_ASN1_NULL:
|
||||
break;
|
||||
|
||||
case V_ASN1_ANY:
|
||||
ASN1_primitive_free(pval, NULL);
|
||||
OPENSSL_free(*pval);
|
||||
break;
|
||||
|
||||
default:
|
||||
ASN1_STRING_free((ASN1_STRING *)*pval);
|
||||
*pval = NULL;
|
||||
break;
|
||||
}
|
||||
*pval = NULL;
|
||||
}
|
||||
@@ -0,0 +1,244 @@
|
||||
/* Copyright (C) 1995-1998 Eric Young ([email protected])
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young ([email protected]).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson ([email protected]).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young ([email protected])"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson ([email protected])"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.] */
|
||||
|
||||
#include <openssl/asn1.h>
|
||||
|
||||
#include <openssl/asn1t.h>
|
||||
#include <openssl/mem.h>
|
||||
|
||||
#include "asn1_locl.h"
|
||||
|
||||
/* Free up an ASN1 structure */
|
||||
|
||||
void ASN1_item_free(ASN1_VALUE *val, const ASN1_ITEM *it)
|
||||
{
|
||||
asn1_item_combine_free(&val, it, 0);
|
||||
}
|
||||
|
||||
void ASN1_item_ex_free(ASN1_VALUE **pval, const ASN1_ITEM *it)
|
||||
{
|
||||
asn1_item_combine_free(pval, it, 0);
|
||||
}
|
||||
|
||||
void asn1_item_combine_free(ASN1_VALUE **pval, const ASN1_ITEM *it, int combine)
|
||||
{
|
||||
const ASN1_TEMPLATE *tt = NULL, *seqtt;
|
||||
const ASN1_EXTERN_FUNCS *ef;
|
||||
const ASN1_COMPAT_FUNCS *cf;
|
||||
const ASN1_AUX *aux = it->funcs;
|
||||
ASN1_aux_cb *asn1_cb;
|
||||
int i;
|
||||
if (!pval)
|
||||
return;
|
||||
if ((it->itype != ASN1_ITYPE_PRIMITIVE) && !*pval)
|
||||
return;
|
||||
if (aux && aux->asn1_cb)
|
||||
asn1_cb = aux->asn1_cb;
|
||||
else
|
||||
asn1_cb = 0;
|
||||
|
||||
switch (it->itype) {
|
||||
|
||||
case ASN1_ITYPE_PRIMITIVE:
|
||||
if (it->templates)
|
||||
ASN1_template_free(pval, it->templates);
|
||||
else
|
||||
ASN1_primitive_free(pval, it);
|
||||
break;
|
||||
|
||||
case ASN1_ITYPE_MSTRING:
|
||||
ASN1_primitive_free(pval, it);
|
||||
break;
|
||||
|
||||
case ASN1_ITYPE_CHOICE:
|
||||
if (asn1_cb) {
|
||||
i = asn1_cb(ASN1_OP_FREE_PRE, pval, it, NULL);
|
||||
if (i == 2)
|
||||
return;
|
||||
}
|
||||
i = asn1_get_choice_selector(pval, it);
|
||||
if ((i >= 0) && (i < it->tcount)) {
|
||||
ASN1_VALUE **pchval;
|
||||
tt = it->templates + i;
|
||||
pchval = asn1_get_field_ptr(pval, tt);
|
||||
ASN1_template_free(pchval, tt);
|
||||
}
|
||||
if (asn1_cb)
|
||||
asn1_cb(ASN1_OP_FREE_POST, pval, it, NULL);
|
||||
if (!combine) {
|
||||
OPENSSL_free(*pval);
|
||||
*pval = NULL;
|
||||
}
|
||||
break;
|
||||
|
||||
case ASN1_ITYPE_COMPAT:
|
||||
cf = it->funcs;
|
||||
if (cf && cf->asn1_free)
|
||||
cf->asn1_free(*pval);
|
||||
break;
|
||||
|
||||
case ASN1_ITYPE_EXTERN:
|
||||
ef = it->funcs;
|
||||
if (ef && ef->asn1_ex_free)
|
||||
ef->asn1_ex_free(pval, it);
|
||||
break;
|
||||
|
||||
case ASN1_ITYPE_NDEF_SEQUENCE:
|
||||
case ASN1_ITYPE_SEQUENCE:
|
||||
if (!asn1_refcount_dec_and_test_zero(pval, it))
|
||||
return;
|
||||
if (asn1_cb) {
|
||||
i = asn1_cb(ASN1_OP_FREE_PRE, pval, it, NULL);
|
||||
if (i == 2)
|
||||
return;
|
||||
}
|
||||
asn1_enc_free(pval, it);
|
||||
/*
|
||||
* If we free up as normal we will invalidate any ANY DEFINED BY
|
||||
* field and we wont be able to determine the type of the field it
|
||||
* defines. So free up in reverse order.
|
||||
*/
|
||||
tt = it->templates + it->tcount - 1;
|
||||
for (i = 0; i < it->tcount; tt--, i++) {
|
||||
ASN1_VALUE **pseqval;
|
||||
seqtt = asn1_do_adb(pval, tt, 0);
|
||||
if (!seqtt)
|
||||
continue;
|
||||
pseqval = asn1_get_field_ptr(pval, seqtt);
|
||||
ASN1_template_free(pseqval, seqtt);
|
||||
}
|
||||
if (asn1_cb)
|
||||
asn1_cb(ASN1_OP_FREE_POST, pval, it, NULL);
|
||||
if (!combine) {
|
||||
OPENSSL_free(*pval);
|
||||
*pval = NULL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void ASN1_template_free(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt)
|
||||
{
|
||||
size_t i;
|
||||
if (tt->flags & ASN1_TFLG_SK_MASK) {
|
||||
STACK_OF(ASN1_VALUE) *sk = (STACK_OF(ASN1_VALUE) *)*pval;
|
||||
for (i = 0; i < sk_ASN1_VALUE_num(sk); i++) {
|
||||
ASN1_VALUE *vtmp;
|
||||
vtmp = sk_ASN1_VALUE_value(sk, i);
|
||||
asn1_item_combine_free(&vtmp, ASN1_ITEM_ptr(tt->item), 0);
|
||||
}
|
||||
sk_ASN1_VALUE_free(sk);
|
||||
*pval = NULL;
|
||||
} else
|
||||
asn1_item_combine_free(pval, ASN1_ITEM_ptr(tt->item),
|
||||
tt->flags & ASN1_TFLG_COMBINE);
|
||||
}
|
||||
|
||||
void ASN1_primitive_free(ASN1_VALUE **pval, const ASN1_ITEM *it)
|
||||
{
|
||||
int utype;
|
||||
if (it) {
|
||||
const ASN1_PRIMITIVE_FUNCS *pf;
|
||||
pf = it->funcs;
|
||||
if (pf && pf->prim_free) {
|
||||
pf->prim_free(pval, it);
|
||||
return;
|
||||
}
|
||||
}
|
||||
/* Special case: if 'it' is NULL free contents of ASN1_TYPE */
|
||||
if (!it) {
|
||||
ASN1_TYPE *typ = (ASN1_TYPE *)*pval;
|
||||
utype = typ->type;
|
||||
pval = &typ->value.asn1_value;
|
||||
if (!*pval)
|
||||
return;
|
||||
} else if (it->itype == ASN1_ITYPE_MSTRING) {
|
||||
utype = -1;
|
||||
if (!*pval)
|
||||
return;
|
||||
} else {
|
||||
utype = it->utype;
|
||||
if ((utype != V_ASN1_BOOLEAN) && !*pval)
|
||||
return;
|
||||
}
|
||||
|
||||
switch (utype) {
|
||||
case V_ASN1_OBJECT:
|
||||
ASN1_OBJECT_free((ASN1_OBJECT *)*pval);
|
||||
break;
|
||||
|
||||
case V_ASN1_BOOLEAN:
|
||||
if (it)
|
||||
*(ASN1_BOOLEAN *)pval = it->size;
|
||||
else
|
||||
*(ASN1_BOOLEAN *)pval = -1;
|
||||
return;
|
||||
|
||||
case V_ASN1_NULL:
|
||||
break;
|
||||
|
||||
case V_ASN1_ANY:
|
||||
ASN1_primitive_free(pval, NULL);
|
||||
OPENSSL_free(*pval);
|
||||
break;
|
||||
|
||||
default:
|
||||
ASN1_STRING_free((ASN1_STRING *)*pval);
|
||||
*pval = NULL;
|
||||
break;
|
||||
}
|
||||
*pval = NULL;
|
||||
}
|
||||
+387
@@ -0,0 +1,387 @@
|
||||
/* Copyright (C) 1995-1998 Eric Young ([email protected])
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young ([email protected]).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson ([email protected]).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young ([email protected])"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson ([email protected])"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.] */
|
||||
|
||||
#include <openssl_grpc/asn1.h>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <openssl_grpc/asn1t.h>
|
||||
#include <openssl_grpc/err.h>
|
||||
#include <openssl_grpc/mem.h>
|
||||
#include <openssl_grpc/obj.h>
|
||||
|
||||
#include "asn1_locl.h"
|
||||
#include "../internal.h"
|
||||
|
||||
|
||||
static int asn1_item_ex_combine_new(ASN1_VALUE **pval, const ASN1_ITEM *it,
|
||||
int combine);
|
||||
static void asn1_item_clear(ASN1_VALUE **pval, const ASN1_ITEM *it);
|
||||
static void asn1_template_clear(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt);
|
||||
static void asn1_primitive_clear(ASN1_VALUE **pval, const ASN1_ITEM *it);
|
||||
|
||||
ASN1_VALUE *ASN1_item_new(const ASN1_ITEM *it)
|
||||
{
|
||||
ASN1_VALUE *ret = NULL;
|
||||
if (ASN1_item_ex_new(&ret, it) > 0)
|
||||
return ret;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Allocate an ASN1 structure */
|
||||
|
||||
int ASN1_item_ex_new(ASN1_VALUE **pval, const ASN1_ITEM *it)
|
||||
{
|
||||
return asn1_item_ex_combine_new(pval, it, 0);
|
||||
}
|
||||
|
||||
static int asn1_item_ex_combine_new(ASN1_VALUE **pval, const ASN1_ITEM *it,
|
||||
int combine)
|
||||
{
|
||||
const ASN1_TEMPLATE *tt = NULL;
|
||||
const ASN1_COMPAT_FUNCS *cf;
|
||||
const ASN1_EXTERN_FUNCS *ef;
|
||||
const ASN1_AUX *aux = it->funcs;
|
||||
ASN1_aux_cb *asn1_cb;
|
||||
ASN1_VALUE **pseqval;
|
||||
int i;
|
||||
if (aux && aux->asn1_cb)
|
||||
asn1_cb = aux->asn1_cb;
|
||||
else
|
||||
asn1_cb = 0;
|
||||
|
||||
#ifdef CRYPTO_MDEBUG
|
||||
if (it->sname)
|
||||
CRYPTO_push_info(it->sname);
|
||||
#endif
|
||||
|
||||
switch (it->itype) {
|
||||
|
||||
case ASN1_ITYPE_EXTERN:
|
||||
ef = it->funcs;
|
||||
if (ef && ef->asn1_ex_new) {
|
||||
if (!ef->asn1_ex_new(pval, it))
|
||||
goto memerr;
|
||||
}
|
||||
break;
|
||||
|
||||
case ASN1_ITYPE_COMPAT:
|
||||
cf = it->funcs;
|
||||
if (cf && cf->asn1_new) {
|
||||
*pval = cf->asn1_new();
|
||||
if (!*pval)
|
||||
goto memerr;
|
||||
}
|
||||
break;
|
||||
|
||||
case ASN1_ITYPE_PRIMITIVE:
|
||||
if (it->templates) {
|
||||
if (!ASN1_template_new(pval, it->templates))
|
||||
goto memerr;
|
||||
} else if (!ASN1_primitive_new(pval, it))
|
||||
goto memerr;
|
||||
break;
|
||||
|
||||
case ASN1_ITYPE_MSTRING:
|
||||
if (!ASN1_primitive_new(pval, it))
|
||||
goto memerr;
|
||||
break;
|
||||
|
||||
case ASN1_ITYPE_CHOICE:
|
||||
if (asn1_cb) {
|
||||
i = asn1_cb(ASN1_OP_NEW_PRE, pval, it, NULL);
|
||||
if (!i)
|
||||
goto auxerr;
|
||||
if (i == 2) {
|
||||
#ifdef CRYPTO_MDEBUG
|
||||
if (it->sname)
|
||||
CRYPTO_pop_info();
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
if (!combine) {
|
||||
*pval = OPENSSL_malloc(it->size);
|
||||
if (!*pval)
|
||||
goto memerr;
|
||||
OPENSSL_memset(*pval, 0, it->size);
|
||||
}
|
||||
asn1_set_choice_selector(pval, -1, it);
|
||||
if (asn1_cb && !asn1_cb(ASN1_OP_NEW_POST, pval, it, NULL))
|
||||
goto auxerr2;
|
||||
break;
|
||||
|
||||
case ASN1_ITYPE_NDEF_SEQUENCE:
|
||||
case ASN1_ITYPE_SEQUENCE:
|
||||
if (asn1_cb) {
|
||||
i = asn1_cb(ASN1_OP_NEW_PRE, pval, it, NULL);
|
||||
if (!i)
|
||||
goto auxerr;
|
||||
if (i == 2) {
|
||||
#ifdef CRYPTO_MDEBUG
|
||||
if (it->sname)
|
||||
CRYPTO_pop_info();
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
if (!combine) {
|
||||
*pval = OPENSSL_malloc(it->size);
|
||||
if (!*pval)
|
||||
goto memerr;
|
||||
OPENSSL_memset(*pval, 0, it->size);
|
||||
asn1_refcount_set_one(pval, it);
|
||||
asn1_enc_init(pval, it);
|
||||
}
|
||||
for (i = 0, tt = it->templates; i < it->tcount; tt++, i++) {
|
||||
pseqval = asn1_get_field_ptr(pval, tt);
|
||||
if (!ASN1_template_new(pseqval, tt))
|
||||
goto memerr2;
|
||||
}
|
||||
if (asn1_cb && !asn1_cb(ASN1_OP_NEW_POST, pval, it, NULL))
|
||||
goto auxerr2;
|
||||
break;
|
||||
}
|
||||
#ifdef CRYPTO_MDEBUG
|
||||
if (it->sname)
|
||||
CRYPTO_pop_info();
|
||||
#endif
|
||||
return 1;
|
||||
|
||||
memerr2:
|
||||
asn1_item_combine_free(pval, it, combine);
|
||||
memerr:
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
|
||||
#ifdef CRYPTO_MDEBUG
|
||||
if (it->sname)
|
||||
CRYPTO_pop_info();
|
||||
#endif
|
||||
return 0;
|
||||
|
||||
auxerr2:
|
||||
asn1_item_combine_free(pval, it, combine);
|
||||
auxerr:
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_AUX_ERROR);
|
||||
#ifdef CRYPTO_MDEBUG
|
||||
if (it->sname)
|
||||
CRYPTO_pop_info();
|
||||
#endif
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
static void asn1_item_clear(ASN1_VALUE **pval, const ASN1_ITEM *it)
|
||||
{
|
||||
const ASN1_EXTERN_FUNCS *ef;
|
||||
|
||||
switch (it->itype) {
|
||||
|
||||
case ASN1_ITYPE_EXTERN:
|
||||
ef = it->funcs;
|
||||
if (ef && ef->asn1_ex_clear)
|
||||
ef->asn1_ex_clear(pval, it);
|
||||
else
|
||||
*pval = NULL;
|
||||
break;
|
||||
|
||||
case ASN1_ITYPE_PRIMITIVE:
|
||||
if (it->templates)
|
||||
asn1_template_clear(pval, it->templates);
|
||||
else
|
||||
asn1_primitive_clear(pval, it);
|
||||
break;
|
||||
|
||||
case ASN1_ITYPE_MSTRING:
|
||||
asn1_primitive_clear(pval, it);
|
||||
break;
|
||||
|
||||
case ASN1_ITYPE_COMPAT:
|
||||
case ASN1_ITYPE_CHOICE:
|
||||
case ASN1_ITYPE_SEQUENCE:
|
||||
case ASN1_ITYPE_NDEF_SEQUENCE:
|
||||
*pval = NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int ASN1_template_new(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt)
|
||||
{
|
||||
const ASN1_ITEM *it = ASN1_ITEM_ptr(tt->item);
|
||||
int ret;
|
||||
if (tt->flags & ASN1_TFLG_OPTIONAL) {
|
||||
asn1_template_clear(pval, tt);
|
||||
return 1;
|
||||
}
|
||||
/* If ANY DEFINED BY nothing to do */
|
||||
|
||||
if (tt->flags & ASN1_TFLG_ADB_MASK) {
|
||||
*pval = NULL;
|
||||
return 1;
|
||||
}
|
||||
#ifdef CRYPTO_MDEBUG
|
||||
if (tt->field_name)
|
||||
CRYPTO_push_info(tt->field_name);
|
||||
#endif
|
||||
/* If SET OF or SEQUENCE OF, its a STACK */
|
||||
if (tt->flags & ASN1_TFLG_SK_MASK) {
|
||||
STACK_OF(ASN1_VALUE) *skval;
|
||||
skval = sk_ASN1_VALUE_new_null();
|
||||
if (!skval) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
|
||||
ret = 0;
|
||||
goto done;
|
||||
}
|
||||
*pval = (ASN1_VALUE *)skval;
|
||||
ret = 1;
|
||||
goto done;
|
||||
}
|
||||
/* Otherwise pass it back to the item routine */
|
||||
ret = asn1_item_ex_combine_new(pval, it, tt->flags & ASN1_TFLG_COMBINE);
|
||||
done:
|
||||
#ifdef CRYPTO_MDEBUG
|
||||
if (it->sname)
|
||||
CRYPTO_pop_info();
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void asn1_template_clear(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt)
|
||||
{
|
||||
/* If ADB or STACK just NULL the field */
|
||||
if (tt->flags & (ASN1_TFLG_ADB_MASK | ASN1_TFLG_SK_MASK))
|
||||
*pval = NULL;
|
||||
else
|
||||
asn1_item_clear(pval, ASN1_ITEM_ptr(tt->item));
|
||||
}
|
||||
|
||||
/*
|
||||
* NB: could probably combine most of the real XXX_new() behaviour and junk
|
||||
* all the old functions.
|
||||
*/
|
||||
|
||||
int ASN1_primitive_new(ASN1_VALUE **pval, const ASN1_ITEM *it)
|
||||
{
|
||||
ASN1_TYPE *typ;
|
||||
ASN1_STRING *str;
|
||||
int utype;
|
||||
|
||||
if (!it)
|
||||
return 0;
|
||||
|
||||
if (it->funcs) {
|
||||
const ASN1_PRIMITIVE_FUNCS *pf = it->funcs;
|
||||
if (pf->prim_new)
|
||||
return pf->prim_new(pval, it);
|
||||
}
|
||||
|
||||
if (it->itype == ASN1_ITYPE_MSTRING)
|
||||
utype = -1;
|
||||
else
|
||||
utype = it->utype;
|
||||
switch (utype) {
|
||||
case V_ASN1_OBJECT:
|
||||
*pval = (ASN1_VALUE *)OBJ_nid2obj(NID_undef);
|
||||
return 1;
|
||||
|
||||
case V_ASN1_BOOLEAN:
|
||||
*(ASN1_BOOLEAN *)pval = it->size;
|
||||
return 1;
|
||||
|
||||
case V_ASN1_NULL:
|
||||
*pval = (ASN1_VALUE *)1;
|
||||
return 1;
|
||||
|
||||
case V_ASN1_ANY:
|
||||
typ = OPENSSL_malloc(sizeof(ASN1_TYPE));
|
||||
if (!typ)
|
||||
return 0;
|
||||
typ->value.ptr = NULL;
|
||||
typ->type = -1;
|
||||
*pval = (ASN1_VALUE *)typ;
|
||||
break;
|
||||
|
||||
default:
|
||||
str = ASN1_STRING_type_new(utype);
|
||||
if (it->itype == ASN1_ITYPE_MSTRING && str)
|
||||
str->flags |= ASN1_STRING_FLAG_MSTRING;
|
||||
*pval = (ASN1_VALUE *)str;
|
||||
break;
|
||||
}
|
||||
if (*pval)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void asn1_primitive_clear(ASN1_VALUE **pval, const ASN1_ITEM *it)
|
||||
{
|
||||
int utype;
|
||||
if (it && it->funcs) {
|
||||
const ASN1_PRIMITIVE_FUNCS *pf = it->funcs;
|
||||
if (pf->prim_clear)
|
||||
pf->prim_clear(pval, it);
|
||||
else
|
||||
*pval = NULL;
|
||||
return;
|
||||
}
|
||||
if (!it || (it->itype == ASN1_ITYPE_MSTRING))
|
||||
utype = -1;
|
||||
else
|
||||
utype = it->utype;
|
||||
if (utype == V_ASN1_BOOLEAN)
|
||||
*(ASN1_BOOLEAN *)pval = it->size;
|
||||
else
|
||||
*pval = NULL;
|
||||
}
|
||||
@@ -0,0 +1,387 @@
|
||||
/* Copyright (C) 1995-1998 Eric Young ([email protected])
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young ([email protected]).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson ([email protected]).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young ([email protected])"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson ([email protected])"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.] */
|
||||
|
||||
#include <openssl/asn1.h>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <openssl/asn1t.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/mem.h>
|
||||
#include <openssl/obj.h>
|
||||
|
||||
#include "asn1_locl.h"
|
||||
#include "../internal.h"
|
||||
|
||||
|
||||
static int asn1_item_ex_combine_new(ASN1_VALUE **pval, const ASN1_ITEM *it,
|
||||
int combine);
|
||||
static void asn1_item_clear(ASN1_VALUE **pval, const ASN1_ITEM *it);
|
||||
static void asn1_template_clear(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt);
|
||||
static void asn1_primitive_clear(ASN1_VALUE **pval, const ASN1_ITEM *it);
|
||||
|
||||
ASN1_VALUE *ASN1_item_new(const ASN1_ITEM *it)
|
||||
{
|
||||
ASN1_VALUE *ret = NULL;
|
||||
if (ASN1_item_ex_new(&ret, it) > 0)
|
||||
return ret;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Allocate an ASN1 structure */
|
||||
|
||||
int ASN1_item_ex_new(ASN1_VALUE **pval, const ASN1_ITEM *it)
|
||||
{
|
||||
return asn1_item_ex_combine_new(pval, it, 0);
|
||||
}
|
||||
|
||||
static int asn1_item_ex_combine_new(ASN1_VALUE **pval, const ASN1_ITEM *it,
|
||||
int combine)
|
||||
{
|
||||
const ASN1_TEMPLATE *tt = NULL;
|
||||
const ASN1_COMPAT_FUNCS *cf;
|
||||
const ASN1_EXTERN_FUNCS *ef;
|
||||
const ASN1_AUX *aux = it->funcs;
|
||||
ASN1_aux_cb *asn1_cb;
|
||||
ASN1_VALUE **pseqval;
|
||||
int i;
|
||||
if (aux && aux->asn1_cb)
|
||||
asn1_cb = aux->asn1_cb;
|
||||
else
|
||||
asn1_cb = 0;
|
||||
|
||||
#ifdef CRYPTO_MDEBUG
|
||||
if (it->sname)
|
||||
CRYPTO_push_info(it->sname);
|
||||
#endif
|
||||
|
||||
switch (it->itype) {
|
||||
|
||||
case ASN1_ITYPE_EXTERN:
|
||||
ef = it->funcs;
|
||||
if (ef && ef->asn1_ex_new) {
|
||||
if (!ef->asn1_ex_new(pval, it))
|
||||
goto memerr;
|
||||
}
|
||||
break;
|
||||
|
||||
case ASN1_ITYPE_COMPAT:
|
||||
cf = it->funcs;
|
||||
if (cf && cf->asn1_new) {
|
||||
*pval = cf->asn1_new();
|
||||
if (!*pval)
|
||||
goto memerr;
|
||||
}
|
||||
break;
|
||||
|
||||
case ASN1_ITYPE_PRIMITIVE:
|
||||
if (it->templates) {
|
||||
if (!ASN1_template_new(pval, it->templates))
|
||||
goto memerr;
|
||||
} else if (!ASN1_primitive_new(pval, it))
|
||||
goto memerr;
|
||||
break;
|
||||
|
||||
case ASN1_ITYPE_MSTRING:
|
||||
if (!ASN1_primitive_new(pval, it))
|
||||
goto memerr;
|
||||
break;
|
||||
|
||||
case ASN1_ITYPE_CHOICE:
|
||||
if (asn1_cb) {
|
||||
i = asn1_cb(ASN1_OP_NEW_PRE, pval, it, NULL);
|
||||
if (!i)
|
||||
goto auxerr;
|
||||
if (i == 2) {
|
||||
#ifdef CRYPTO_MDEBUG
|
||||
if (it->sname)
|
||||
CRYPTO_pop_info();
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
if (!combine) {
|
||||
*pval = OPENSSL_malloc(it->size);
|
||||
if (!*pval)
|
||||
goto memerr;
|
||||
OPENSSL_memset(*pval, 0, it->size);
|
||||
}
|
||||
asn1_set_choice_selector(pval, -1, it);
|
||||
if (asn1_cb && !asn1_cb(ASN1_OP_NEW_POST, pval, it, NULL))
|
||||
goto auxerr2;
|
||||
break;
|
||||
|
||||
case ASN1_ITYPE_NDEF_SEQUENCE:
|
||||
case ASN1_ITYPE_SEQUENCE:
|
||||
if (asn1_cb) {
|
||||
i = asn1_cb(ASN1_OP_NEW_PRE, pval, it, NULL);
|
||||
if (!i)
|
||||
goto auxerr;
|
||||
if (i == 2) {
|
||||
#ifdef CRYPTO_MDEBUG
|
||||
if (it->sname)
|
||||
CRYPTO_pop_info();
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
if (!combine) {
|
||||
*pval = OPENSSL_malloc(it->size);
|
||||
if (!*pval)
|
||||
goto memerr;
|
||||
OPENSSL_memset(*pval, 0, it->size);
|
||||
asn1_refcount_set_one(pval, it);
|
||||
asn1_enc_init(pval, it);
|
||||
}
|
||||
for (i = 0, tt = it->templates; i < it->tcount; tt++, i++) {
|
||||
pseqval = asn1_get_field_ptr(pval, tt);
|
||||
if (!ASN1_template_new(pseqval, tt))
|
||||
goto memerr2;
|
||||
}
|
||||
if (asn1_cb && !asn1_cb(ASN1_OP_NEW_POST, pval, it, NULL))
|
||||
goto auxerr2;
|
||||
break;
|
||||
}
|
||||
#ifdef CRYPTO_MDEBUG
|
||||
if (it->sname)
|
||||
CRYPTO_pop_info();
|
||||
#endif
|
||||
return 1;
|
||||
|
||||
memerr2:
|
||||
asn1_item_combine_free(pval, it, combine);
|
||||
memerr:
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
|
||||
#ifdef CRYPTO_MDEBUG
|
||||
if (it->sname)
|
||||
CRYPTO_pop_info();
|
||||
#endif
|
||||
return 0;
|
||||
|
||||
auxerr2:
|
||||
asn1_item_combine_free(pval, it, combine);
|
||||
auxerr:
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_AUX_ERROR);
|
||||
#ifdef CRYPTO_MDEBUG
|
||||
if (it->sname)
|
||||
CRYPTO_pop_info();
|
||||
#endif
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
static void asn1_item_clear(ASN1_VALUE **pval, const ASN1_ITEM *it)
|
||||
{
|
||||
const ASN1_EXTERN_FUNCS *ef;
|
||||
|
||||
switch (it->itype) {
|
||||
|
||||
case ASN1_ITYPE_EXTERN:
|
||||
ef = it->funcs;
|
||||
if (ef && ef->asn1_ex_clear)
|
||||
ef->asn1_ex_clear(pval, it);
|
||||
else
|
||||
*pval = NULL;
|
||||
break;
|
||||
|
||||
case ASN1_ITYPE_PRIMITIVE:
|
||||
if (it->templates)
|
||||
asn1_template_clear(pval, it->templates);
|
||||
else
|
||||
asn1_primitive_clear(pval, it);
|
||||
break;
|
||||
|
||||
case ASN1_ITYPE_MSTRING:
|
||||
asn1_primitive_clear(pval, it);
|
||||
break;
|
||||
|
||||
case ASN1_ITYPE_COMPAT:
|
||||
case ASN1_ITYPE_CHOICE:
|
||||
case ASN1_ITYPE_SEQUENCE:
|
||||
case ASN1_ITYPE_NDEF_SEQUENCE:
|
||||
*pval = NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int ASN1_template_new(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt)
|
||||
{
|
||||
const ASN1_ITEM *it = ASN1_ITEM_ptr(tt->item);
|
||||
int ret;
|
||||
if (tt->flags & ASN1_TFLG_OPTIONAL) {
|
||||
asn1_template_clear(pval, tt);
|
||||
return 1;
|
||||
}
|
||||
/* If ANY DEFINED BY nothing to do */
|
||||
|
||||
if (tt->flags & ASN1_TFLG_ADB_MASK) {
|
||||
*pval = NULL;
|
||||
return 1;
|
||||
}
|
||||
#ifdef CRYPTO_MDEBUG
|
||||
if (tt->field_name)
|
||||
CRYPTO_push_info(tt->field_name);
|
||||
#endif
|
||||
/* If SET OF or SEQUENCE OF, its a STACK */
|
||||
if (tt->flags & ASN1_TFLG_SK_MASK) {
|
||||
STACK_OF(ASN1_VALUE) *skval;
|
||||
skval = sk_ASN1_VALUE_new_null();
|
||||
if (!skval) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
|
||||
ret = 0;
|
||||
goto done;
|
||||
}
|
||||
*pval = (ASN1_VALUE *)skval;
|
||||
ret = 1;
|
||||
goto done;
|
||||
}
|
||||
/* Otherwise pass it back to the item routine */
|
||||
ret = asn1_item_ex_combine_new(pval, it, tt->flags & ASN1_TFLG_COMBINE);
|
||||
done:
|
||||
#ifdef CRYPTO_MDEBUG
|
||||
if (it->sname)
|
||||
CRYPTO_pop_info();
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void asn1_template_clear(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt)
|
||||
{
|
||||
/* If ADB or STACK just NULL the field */
|
||||
if (tt->flags & (ASN1_TFLG_ADB_MASK | ASN1_TFLG_SK_MASK))
|
||||
*pval = NULL;
|
||||
else
|
||||
asn1_item_clear(pval, ASN1_ITEM_ptr(tt->item));
|
||||
}
|
||||
|
||||
/*
|
||||
* NB: could probably combine most of the real XXX_new() behaviour and junk
|
||||
* all the old functions.
|
||||
*/
|
||||
|
||||
int ASN1_primitive_new(ASN1_VALUE **pval, const ASN1_ITEM *it)
|
||||
{
|
||||
ASN1_TYPE *typ;
|
||||
ASN1_STRING *str;
|
||||
int utype;
|
||||
|
||||
if (!it)
|
||||
return 0;
|
||||
|
||||
if (it->funcs) {
|
||||
const ASN1_PRIMITIVE_FUNCS *pf = it->funcs;
|
||||
if (pf->prim_new)
|
||||
return pf->prim_new(pval, it);
|
||||
}
|
||||
|
||||
if (it->itype == ASN1_ITYPE_MSTRING)
|
||||
utype = -1;
|
||||
else
|
||||
utype = it->utype;
|
||||
switch (utype) {
|
||||
case V_ASN1_OBJECT:
|
||||
*pval = (ASN1_VALUE *)OBJ_nid2obj(NID_undef);
|
||||
return 1;
|
||||
|
||||
case V_ASN1_BOOLEAN:
|
||||
*(ASN1_BOOLEAN *)pval = it->size;
|
||||
return 1;
|
||||
|
||||
case V_ASN1_NULL:
|
||||
*pval = (ASN1_VALUE *)1;
|
||||
return 1;
|
||||
|
||||
case V_ASN1_ANY:
|
||||
typ = OPENSSL_malloc(sizeof(ASN1_TYPE));
|
||||
if (!typ)
|
||||
return 0;
|
||||
typ->value.ptr = NULL;
|
||||
typ->type = -1;
|
||||
*pval = (ASN1_VALUE *)typ;
|
||||
break;
|
||||
|
||||
default:
|
||||
str = ASN1_STRING_type_new(utype);
|
||||
if (it->itype == ASN1_ITYPE_MSTRING && str)
|
||||
str->flags |= ASN1_STRING_FLAG_MSTRING;
|
||||
*pval = (ASN1_VALUE *)str;
|
||||
break;
|
||||
}
|
||||
if (*pval)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void asn1_primitive_clear(ASN1_VALUE **pval, const ASN1_ITEM *it)
|
||||
{
|
||||
int utype;
|
||||
if (it && it->funcs) {
|
||||
const ASN1_PRIMITIVE_FUNCS *pf = it->funcs;
|
||||
if (pf->prim_clear)
|
||||
pf->prim_clear(pval, it);
|
||||
else
|
||||
*pval = NULL;
|
||||
return;
|
||||
}
|
||||
if (!it || (it->itype == ASN1_ITYPE_MSTRING))
|
||||
utype = -1;
|
||||
else
|
||||
utype = it->utype;
|
||||
if (utype == V_ASN1_BOOLEAN)
|
||||
*(ASN1_BOOLEAN *)pval = it->size;
|
||||
else
|
||||
*pval = NULL;
|
||||
}
|
||||
+131
@@ -0,0 +1,131 @@
|
||||
/* Copyright (C) 1995-1998 Eric Young ([email protected])
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young ([email protected]).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson ([email protected]).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young ([email protected])"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson ([email protected])"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.] */
|
||||
|
||||
#include <openssl_grpc/asn1.h>
|
||||
|
||||
#include <openssl_grpc/asn1t.h>
|
||||
|
||||
/* Declarations for string types */
|
||||
|
||||
#define IMPLEMENT_ASN1_STRING_FUNCTIONS(sname) \
|
||||
IMPLEMENT_ASN1_TYPE(sname) \
|
||||
IMPLEMENT_ASN1_ENCODE_FUNCTIONS_fname(sname, sname, sname) \
|
||||
sname *sname##_new(void) \
|
||||
{ \
|
||||
return ASN1_STRING_type_new(V_##sname); \
|
||||
} \
|
||||
void sname##_free(sname *x) \
|
||||
{ \
|
||||
ASN1_STRING_free(x); \
|
||||
}
|
||||
|
||||
IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_OCTET_STRING)
|
||||
IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_INTEGER)
|
||||
IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_ENUMERATED)
|
||||
IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_BIT_STRING)
|
||||
IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_UTF8STRING)
|
||||
IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_PRINTABLESTRING)
|
||||
IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_T61STRING)
|
||||
IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_IA5STRING)
|
||||
IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_GENERALSTRING)
|
||||
IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_UTCTIME)
|
||||
IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_GENERALIZEDTIME)
|
||||
IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_VISIBLESTRING)
|
||||
IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_UNIVERSALSTRING)
|
||||
IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_BMPSTRING)
|
||||
|
||||
IMPLEMENT_ASN1_TYPE(ASN1_NULL)
|
||||
IMPLEMENT_ASN1_FUNCTIONS(ASN1_NULL)
|
||||
|
||||
IMPLEMENT_ASN1_TYPE(ASN1_OBJECT)
|
||||
|
||||
IMPLEMENT_ASN1_TYPE(ASN1_ANY)
|
||||
|
||||
/* Just swallow an ASN1_SEQUENCE in an ASN1_STRING */
|
||||
IMPLEMENT_ASN1_TYPE(ASN1_SEQUENCE)
|
||||
|
||||
IMPLEMENT_ASN1_FUNCTIONS_fname(ASN1_TYPE, ASN1_ANY, ASN1_TYPE)
|
||||
|
||||
/* Multistring types */
|
||||
|
||||
IMPLEMENT_ASN1_MSTRING(ASN1_PRINTABLE, B_ASN1_PRINTABLE)
|
||||
IMPLEMENT_ASN1_FUNCTIONS_name(ASN1_STRING, ASN1_PRINTABLE)
|
||||
|
||||
IMPLEMENT_ASN1_MSTRING(DISPLAYTEXT, B_ASN1_DISPLAYTEXT)
|
||||
IMPLEMENT_ASN1_FUNCTIONS_name(ASN1_STRING, DISPLAYTEXT)
|
||||
|
||||
IMPLEMENT_ASN1_MSTRING(DIRECTORYSTRING, B_ASN1_DIRECTORYSTRING)
|
||||
IMPLEMENT_ASN1_FUNCTIONS_name(ASN1_STRING, DIRECTORYSTRING)
|
||||
|
||||
/* Three separate BOOLEAN type: normal, DEFAULT TRUE and DEFAULT FALSE */
|
||||
IMPLEMENT_ASN1_TYPE_ex(ASN1_BOOLEAN, ASN1_BOOLEAN, -1)
|
||||
IMPLEMENT_ASN1_TYPE_ex(ASN1_TBOOLEAN, ASN1_BOOLEAN, 1)
|
||||
IMPLEMENT_ASN1_TYPE_ex(ASN1_FBOOLEAN, ASN1_BOOLEAN, 0)
|
||||
|
||||
/* Special, OCTET STRING with indefinite length constructed support */
|
||||
|
||||
IMPLEMENT_ASN1_TYPE_ex(ASN1_OCTET_STRING_NDEF, ASN1_OCTET_STRING, ASN1_TFLG_NDEF)
|
||||
|
||||
ASN1_ITEM_TEMPLATE(ASN1_SEQUENCE_ANY) =
|
||||
ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, ASN1_SEQUENCE_ANY, ASN1_ANY)
|
||||
ASN1_ITEM_TEMPLATE_END(ASN1_SEQUENCE_ANY)
|
||||
|
||||
ASN1_ITEM_TEMPLATE(ASN1_SET_ANY) =
|
||||
ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SET_OF, 0, ASN1_SET_ANY, ASN1_ANY)
|
||||
ASN1_ITEM_TEMPLATE_END(ASN1_SET_ANY)
|
||||
|
||||
IMPLEMENT_ASN1_ENCODE_FUNCTIONS_const_fname(ASN1_SEQUENCE_ANY, ASN1_SEQUENCE_ANY, ASN1_SEQUENCE_ANY)
|
||||
IMPLEMENT_ASN1_ENCODE_FUNCTIONS_const_fname(ASN1_SEQUENCE_ANY, ASN1_SET_ANY, ASN1_SET_ANY)
|
||||
@@ -0,0 +1,131 @@
|
||||
/* Copyright (C) 1995-1998 Eric Young ([email protected])
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young ([email protected]).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson ([email protected]).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young ([email protected])"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson ([email protected])"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.] */
|
||||
|
||||
#include <openssl/asn1.h>
|
||||
|
||||
#include <openssl/asn1t.h>
|
||||
|
||||
/* Declarations for string types */
|
||||
|
||||
#define IMPLEMENT_ASN1_STRING_FUNCTIONS(sname) \
|
||||
IMPLEMENT_ASN1_TYPE(sname) \
|
||||
IMPLEMENT_ASN1_ENCODE_FUNCTIONS_fname(sname, sname, sname) \
|
||||
sname *sname##_new(void) \
|
||||
{ \
|
||||
return ASN1_STRING_type_new(V_##sname); \
|
||||
} \
|
||||
void sname##_free(sname *x) \
|
||||
{ \
|
||||
ASN1_STRING_free(x); \
|
||||
}
|
||||
|
||||
IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_OCTET_STRING)
|
||||
IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_INTEGER)
|
||||
IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_ENUMERATED)
|
||||
IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_BIT_STRING)
|
||||
IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_UTF8STRING)
|
||||
IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_PRINTABLESTRING)
|
||||
IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_T61STRING)
|
||||
IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_IA5STRING)
|
||||
IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_GENERALSTRING)
|
||||
IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_UTCTIME)
|
||||
IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_GENERALIZEDTIME)
|
||||
IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_VISIBLESTRING)
|
||||
IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_UNIVERSALSTRING)
|
||||
IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_BMPSTRING)
|
||||
|
||||
IMPLEMENT_ASN1_TYPE(ASN1_NULL)
|
||||
IMPLEMENT_ASN1_FUNCTIONS(ASN1_NULL)
|
||||
|
||||
IMPLEMENT_ASN1_TYPE(ASN1_OBJECT)
|
||||
|
||||
IMPLEMENT_ASN1_TYPE(ASN1_ANY)
|
||||
|
||||
/* Just swallow an ASN1_SEQUENCE in an ASN1_STRING */
|
||||
IMPLEMENT_ASN1_TYPE(ASN1_SEQUENCE)
|
||||
|
||||
IMPLEMENT_ASN1_FUNCTIONS_fname(ASN1_TYPE, ASN1_ANY, ASN1_TYPE)
|
||||
|
||||
/* Multistring types */
|
||||
|
||||
IMPLEMENT_ASN1_MSTRING(ASN1_PRINTABLE, B_ASN1_PRINTABLE)
|
||||
IMPLEMENT_ASN1_FUNCTIONS_name(ASN1_STRING, ASN1_PRINTABLE)
|
||||
|
||||
IMPLEMENT_ASN1_MSTRING(DISPLAYTEXT, B_ASN1_DISPLAYTEXT)
|
||||
IMPLEMENT_ASN1_FUNCTIONS_name(ASN1_STRING, DISPLAYTEXT)
|
||||
|
||||
IMPLEMENT_ASN1_MSTRING(DIRECTORYSTRING, B_ASN1_DIRECTORYSTRING)
|
||||
IMPLEMENT_ASN1_FUNCTIONS_name(ASN1_STRING, DIRECTORYSTRING)
|
||||
|
||||
/* Three separate BOOLEAN type: normal, DEFAULT TRUE and DEFAULT FALSE */
|
||||
IMPLEMENT_ASN1_TYPE_ex(ASN1_BOOLEAN, ASN1_BOOLEAN, -1)
|
||||
IMPLEMENT_ASN1_TYPE_ex(ASN1_TBOOLEAN, ASN1_BOOLEAN, 1)
|
||||
IMPLEMENT_ASN1_TYPE_ex(ASN1_FBOOLEAN, ASN1_BOOLEAN, 0)
|
||||
|
||||
/* Special, OCTET STRING with indefinite length constructed support */
|
||||
|
||||
IMPLEMENT_ASN1_TYPE_ex(ASN1_OCTET_STRING_NDEF, ASN1_OCTET_STRING, ASN1_TFLG_NDEF)
|
||||
|
||||
ASN1_ITEM_TEMPLATE(ASN1_SEQUENCE_ANY) =
|
||||
ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, ASN1_SEQUENCE_ANY, ASN1_ANY)
|
||||
ASN1_ITEM_TEMPLATE_END(ASN1_SEQUENCE_ANY)
|
||||
|
||||
ASN1_ITEM_TEMPLATE(ASN1_SET_ANY) =
|
||||
ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SET_OF, 0, ASN1_SET_ANY, ASN1_ANY)
|
||||
ASN1_ITEM_TEMPLATE_END(ASN1_SET_ANY)
|
||||
|
||||
IMPLEMENT_ASN1_ENCODE_FUNCTIONS_const_fname(ASN1_SEQUENCE_ANY, ASN1_SEQUENCE_ANY, ASN1_SEQUENCE_ANY)
|
||||
IMPLEMENT_ASN1_ENCODE_FUNCTIONS_const_fname(ASN1_SEQUENCE_ANY, ASN1_SET_ANY, ASN1_SET_ANY)
|
||||
+280
@@ -0,0 +1,280 @@
|
||||
/* Copyright (C) 1995-1998 Eric Young ([email protected])
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young ([email protected]).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson ([email protected]).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young ([email protected])"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson ([email protected])"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.] */
|
||||
|
||||
#include <openssl_grpc/asn1.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <openssl_grpc/asn1t.h>
|
||||
#include <openssl_grpc/mem.h>
|
||||
#include <openssl_grpc/obj.h>
|
||||
#include <openssl_grpc/err.h>
|
||||
#include <openssl_grpc/thread.h>
|
||||
|
||||
#include "../internal.h"
|
||||
|
||||
|
||||
/* Utility functions for manipulating fields and offsets */
|
||||
|
||||
/* Add 'offset' to 'addr' */
|
||||
#define offset2ptr(addr, offset) (void *)(((char *)(addr)) + (offset))
|
||||
|
||||
/* Given an ASN1_ITEM CHOICE type return the selector value */
|
||||
int asn1_get_choice_selector(ASN1_VALUE **pval, const ASN1_ITEM *it) {
|
||||
int *sel = offset2ptr(*pval, it->utype);
|
||||
return *sel;
|
||||
}
|
||||
|
||||
/* Given an ASN1_ITEM CHOICE type set the selector value, return old value. */
|
||||
int asn1_set_choice_selector(ASN1_VALUE **pval, int value,
|
||||
const ASN1_ITEM *it) {
|
||||
int *sel, ret;
|
||||
sel = offset2ptr(*pval, it->utype);
|
||||
ret = *sel;
|
||||
*sel = value;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static CRYPTO_refcount_t *asn1_get_references(ASN1_VALUE **pval,
|
||||
const ASN1_ITEM *it) {
|
||||
if (it->itype != ASN1_ITYPE_SEQUENCE &&
|
||||
it->itype != ASN1_ITYPE_NDEF_SEQUENCE) {
|
||||
return NULL;
|
||||
}
|
||||
const ASN1_AUX *aux = it->funcs;
|
||||
if (!aux || !(aux->flags & ASN1_AFLG_REFCOUNT)) {
|
||||
return NULL;
|
||||
}
|
||||
return offset2ptr(*pval, aux->ref_offset);
|
||||
}
|
||||
|
||||
void asn1_refcount_set_one(ASN1_VALUE **pval, const ASN1_ITEM *it) {
|
||||
CRYPTO_refcount_t *references = asn1_get_references(pval, it);
|
||||
if (references != NULL) {
|
||||
*references = 1;
|
||||
}
|
||||
}
|
||||
|
||||
int asn1_refcount_dec_and_test_zero(ASN1_VALUE **pval, const ASN1_ITEM *it) {
|
||||
CRYPTO_refcount_t *references = asn1_get_references(pval, it);
|
||||
if (references != NULL) {
|
||||
return CRYPTO_refcount_dec_and_test_zero(references);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static ASN1_ENCODING *asn1_get_enc_ptr(ASN1_VALUE **pval, const ASN1_ITEM *it) {
|
||||
const ASN1_AUX *aux;
|
||||
if (!pval || !*pval) {
|
||||
return NULL;
|
||||
}
|
||||
aux = it->funcs;
|
||||
if (!aux || !(aux->flags & ASN1_AFLG_ENCODING)) {
|
||||
return NULL;
|
||||
}
|
||||
return offset2ptr(*pval, aux->enc_offset);
|
||||
}
|
||||
|
||||
void asn1_enc_init(ASN1_VALUE **pval, const ASN1_ITEM *it) {
|
||||
ASN1_ENCODING *enc;
|
||||
enc = asn1_get_enc_ptr(pval, it);
|
||||
if (enc) {
|
||||
enc->enc = NULL;
|
||||
enc->len = 0;
|
||||
enc->alias_only = 0;
|
||||
enc->alias_only_on_next_parse = 0;
|
||||
enc->modified = 1;
|
||||
}
|
||||
}
|
||||
|
||||
void asn1_enc_free(ASN1_VALUE **pval, const ASN1_ITEM *it) {
|
||||
ASN1_ENCODING *enc;
|
||||
enc = asn1_get_enc_ptr(pval, it);
|
||||
if (enc) {
|
||||
if (enc->enc && !enc->alias_only) {
|
||||
OPENSSL_free(enc->enc);
|
||||
}
|
||||
enc->enc = NULL;
|
||||
enc->len = 0;
|
||||
enc->alias_only = 0;
|
||||
enc->alias_only_on_next_parse = 0;
|
||||
enc->modified = 1;
|
||||
}
|
||||
}
|
||||
|
||||
int asn1_enc_save(ASN1_VALUE **pval, const unsigned char *in, int inlen,
|
||||
const ASN1_ITEM *it) {
|
||||
ASN1_ENCODING *enc;
|
||||
enc = asn1_get_enc_ptr(pval, it);
|
||||
if (!enc) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!enc->alias_only) {
|
||||
OPENSSL_free(enc->enc);
|
||||
}
|
||||
|
||||
enc->alias_only = enc->alias_only_on_next_parse;
|
||||
enc->alias_only_on_next_parse = 0;
|
||||
|
||||
if (enc->alias_only) {
|
||||
enc->enc = (uint8_t *) in;
|
||||
} else {
|
||||
enc->enc = OPENSSL_malloc(inlen);
|
||||
if (!enc->enc) {
|
||||
return 0;
|
||||
}
|
||||
OPENSSL_memcpy(enc->enc, in, inlen);
|
||||
}
|
||||
|
||||
enc->len = inlen;
|
||||
enc->modified = 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int asn1_enc_restore(int *len, unsigned char **out, ASN1_VALUE **pval,
|
||||
const ASN1_ITEM *it) {
|
||||
ASN1_ENCODING *enc;
|
||||
enc = asn1_get_enc_ptr(pval, it);
|
||||
if (!enc || enc->modified) {
|
||||
return 0;
|
||||
}
|
||||
if (out) {
|
||||
OPENSSL_memcpy(*out, enc->enc, enc->len);
|
||||
*out += enc->len;
|
||||
}
|
||||
if (len) {
|
||||
*len = enc->len;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Given an ASN1_TEMPLATE get a pointer to a field */
|
||||
ASN1_VALUE **asn1_get_field_ptr(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt) {
|
||||
ASN1_VALUE **pvaltmp;
|
||||
if (tt->flags & ASN1_TFLG_COMBINE) {
|
||||
return pval;
|
||||
}
|
||||
pvaltmp = offset2ptr(*pval, tt->offset);
|
||||
/* NOTE for BOOLEAN types the field is just a plain int so we can't return
|
||||
* int **, so settle for (int *). */
|
||||
return pvaltmp;
|
||||
}
|
||||
|
||||
/* Handle ANY DEFINED BY template, find the selector, look up the relevant
|
||||
* ASN1_TEMPLATE in the table and return it. */
|
||||
const ASN1_TEMPLATE *asn1_do_adb(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt,
|
||||
int nullerr) {
|
||||
const ASN1_ADB *adb;
|
||||
const ASN1_ADB_TABLE *atbl;
|
||||
long selector;
|
||||
ASN1_VALUE **sfld;
|
||||
int i;
|
||||
if (!(tt->flags & ASN1_TFLG_ADB_MASK)) {
|
||||
return tt;
|
||||
}
|
||||
|
||||
/* Else ANY DEFINED BY ... get the table */
|
||||
adb = ASN1_ADB_ptr(tt->item);
|
||||
|
||||
/* Get the selector field */
|
||||
sfld = offset2ptr(*pval, adb->offset);
|
||||
|
||||
/* Check if NULL */
|
||||
if (*sfld == NULL) {
|
||||
if (!adb->null_tt) {
|
||||
goto err;
|
||||
}
|
||||
return adb->null_tt;
|
||||
}
|
||||
|
||||
/* Convert type to a long:
|
||||
* NB: don't check for NID_undef here because it
|
||||
* might be a legitimate value in the table */
|
||||
if (tt->flags & ASN1_TFLG_ADB_OID) {
|
||||
selector = OBJ_obj2nid((ASN1_OBJECT *)*sfld);
|
||||
} else {
|
||||
selector = ASN1_INTEGER_get((ASN1_INTEGER *)*sfld);
|
||||
}
|
||||
|
||||
/* Try to find matching entry in table Maybe should check application types
|
||||
* first to allow application override? Might also be useful to have a flag
|
||||
* which indicates table is sorted and we can do a binary search. For now
|
||||
* stick to a linear search. */
|
||||
|
||||
for (atbl = adb->tbl, i = 0; i < adb->tblcount; i++, atbl++) {
|
||||
if (atbl->value == selector) {
|
||||
return &atbl->tt;
|
||||
}
|
||||
}
|
||||
|
||||
/* FIXME: need to search application table too */
|
||||
|
||||
/* No match, return default type */
|
||||
if (!adb->default_tt) {
|
||||
goto err;
|
||||
}
|
||||
return adb->default_tt;
|
||||
|
||||
err:
|
||||
/* FIXME: should log the value or OID of unsupported type */
|
||||
if (nullerr) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_UNSUPPORTED_ANY_DEFINED_BY_TYPE);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
@@ -0,0 +1,280 @@
|
||||
/* Copyright (C) 1995-1998 Eric Young ([email protected])
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young ([email protected]).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson ([email protected]).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young ([email protected])"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson ([email protected])"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.] */
|
||||
|
||||
#include <openssl/asn1.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <openssl/asn1t.h>
|
||||
#include <openssl/mem.h>
|
||||
#include <openssl/obj.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/thread.h>
|
||||
|
||||
#include "../internal.h"
|
||||
|
||||
|
||||
/* Utility functions for manipulating fields and offsets */
|
||||
|
||||
/* Add 'offset' to 'addr' */
|
||||
#define offset2ptr(addr, offset) (void *)(((char *)(addr)) + (offset))
|
||||
|
||||
/* Given an ASN1_ITEM CHOICE type return the selector value */
|
||||
int asn1_get_choice_selector(ASN1_VALUE **pval, const ASN1_ITEM *it) {
|
||||
int *sel = offset2ptr(*pval, it->utype);
|
||||
return *sel;
|
||||
}
|
||||
|
||||
/* Given an ASN1_ITEM CHOICE type set the selector value, return old value. */
|
||||
int asn1_set_choice_selector(ASN1_VALUE **pval, int value,
|
||||
const ASN1_ITEM *it) {
|
||||
int *sel, ret;
|
||||
sel = offset2ptr(*pval, it->utype);
|
||||
ret = *sel;
|
||||
*sel = value;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static CRYPTO_refcount_t *asn1_get_references(ASN1_VALUE **pval,
|
||||
const ASN1_ITEM *it) {
|
||||
if (it->itype != ASN1_ITYPE_SEQUENCE &&
|
||||
it->itype != ASN1_ITYPE_NDEF_SEQUENCE) {
|
||||
return NULL;
|
||||
}
|
||||
const ASN1_AUX *aux = it->funcs;
|
||||
if (!aux || !(aux->flags & ASN1_AFLG_REFCOUNT)) {
|
||||
return NULL;
|
||||
}
|
||||
return offset2ptr(*pval, aux->ref_offset);
|
||||
}
|
||||
|
||||
void asn1_refcount_set_one(ASN1_VALUE **pval, const ASN1_ITEM *it) {
|
||||
CRYPTO_refcount_t *references = asn1_get_references(pval, it);
|
||||
if (references != NULL) {
|
||||
*references = 1;
|
||||
}
|
||||
}
|
||||
|
||||
int asn1_refcount_dec_and_test_zero(ASN1_VALUE **pval, const ASN1_ITEM *it) {
|
||||
CRYPTO_refcount_t *references = asn1_get_references(pval, it);
|
||||
if (references != NULL) {
|
||||
return CRYPTO_refcount_dec_and_test_zero(references);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static ASN1_ENCODING *asn1_get_enc_ptr(ASN1_VALUE **pval, const ASN1_ITEM *it) {
|
||||
const ASN1_AUX *aux;
|
||||
if (!pval || !*pval) {
|
||||
return NULL;
|
||||
}
|
||||
aux = it->funcs;
|
||||
if (!aux || !(aux->flags & ASN1_AFLG_ENCODING)) {
|
||||
return NULL;
|
||||
}
|
||||
return offset2ptr(*pval, aux->enc_offset);
|
||||
}
|
||||
|
||||
void asn1_enc_init(ASN1_VALUE **pval, const ASN1_ITEM *it) {
|
||||
ASN1_ENCODING *enc;
|
||||
enc = asn1_get_enc_ptr(pval, it);
|
||||
if (enc) {
|
||||
enc->enc = NULL;
|
||||
enc->len = 0;
|
||||
enc->alias_only = 0;
|
||||
enc->alias_only_on_next_parse = 0;
|
||||
enc->modified = 1;
|
||||
}
|
||||
}
|
||||
|
||||
void asn1_enc_free(ASN1_VALUE **pval, const ASN1_ITEM *it) {
|
||||
ASN1_ENCODING *enc;
|
||||
enc = asn1_get_enc_ptr(pval, it);
|
||||
if (enc) {
|
||||
if (enc->enc && !enc->alias_only) {
|
||||
OPENSSL_free(enc->enc);
|
||||
}
|
||||
enc->enc = NULL;
|
||||
enc->len = 0;
|
||||
enc->alias_only = 0;
|
||||
enc->alias_only_on_next_parse = 0;
|
||||
enc->modified = 1;
|
||||
}
|
||||
}
|
||||
|
||||
int asn1_enc_save(ASN1_VALUE **pval, const unsigned char *in, int inlen,
|
||||
const ASN1_ITEM *it) {
|
||||
ASN1_ENCODING *enc;
|
||||
enc = asn1_get_enc_ptr(pval, it);
|
||||
if (!enc) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!enc->alias_only) {
|
||||
OPENSSL_free(enc->enc);
|
||||
}
|
||||
|
||||
enc->alias_only = enc->alias_only_on_next_parse;
|
||||
enc->alias_only_on_next_parse = 0;
|
||||
|
||||
if (enc->alias_only) {
|
||||
enc->enc = (uint8_t *) in;
|
||||
} else {
|
||||
enc->enc = OPENSSL_malloc(inlen);
|
||||
if (!enc->enc) {
|
||||
return 0;
|
||||
}
|
||||
OPENSSL_memcpy(enc->enc, in, inlen);
|
||||
}
|
||||
|
||||
enc->len = inlen;
|
||||
enc->modified = 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int asn1_enc_restore(int *len, unsigned char **out, ASN1_VALUE **pval,
|
||||
const ASN1_ITEM *it) {
|
||||
ASN1_ENCODING *enc;
|
||||
enc = asn1_get_enc_ptr(pval, it);
|
||||
if (!enc || enc->modified) {
|
||||
return 0;
|
||||
}
|
||||
if (out) {
|
||||
OPENSSL_memcpy(*out, enc->enc, enc->len);
|
||||
*out += enc->len;
|
||||
}
|
||||
if (len) {
|
||||
*len = enc->len;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Given an ASN1_TEMPLATE get a pointer to a field */
|
||||
ASN1_VALUE **asn1_get_field_ptr(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt) {
|
||||
ASN1_VALUE **pvaltmp;
|
||||
if (tt->flags & ASN1_TFLG_COMBINE) {
|
||||
return pval;
|
||||
}
|
||||
pvaltmp = offset2ptr(*pval, tt->offset);
|
||||
/* NOTE for BOOLEAN types the field is just a plain int so we can't return
|
||||
* int **, so settle for (int *). */
|
||||
return pvaltmp;
|
||||
}
|
||||
|
||||
/* Handle ANY DEFINED BY template, find the selector, look up the relevant
|
||||
* ASN1_TEMPLATE in the table and return it. */
|
||||
const ASN1_TEMPLATE *asn1_do_adb(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt,
|
||||
int nullerr) {
|
||||
const ASN1_ADB *adb;
|
||||
const ASN1_ADB_TABLE *atbl;
|
||||
long selector;
|
||||
ASN1_VALUE **sfld;
|
||||
int i;
|
||||
if (!(tt->flags & ASN1_TFLG_ADB_MASK)) {
|
||||
return tt;
|
||||
}
|
||||
|
||||
/* Else ANY DEFINED BY ... get the table */
|
||||
adb = ASN1_ADB_ptr(tt->item);
|
||||
|
||||
/* Get the selector field */
|
||||
sfld = offset2ptr(*pval, adb->offset);
|
||||
|
||||
/* Check if NULL */
|
||||
if (*sfld == NULL) {
|
||||
if (!adb->null_tt) {
|
||||
goto err;
|
||||
}
|
||||
return adb->null_tt;
|
||||
}
|
||||
|
||||
/* Convert type to a long:
|
||||
* NB: don't check for NID_undef here because it
|
||||
* might be a legitimate value in the table */
|
||||
if (tt->flags & ASN1_TFLG_ADB_OID) {
|
||||
selector = OBJ_obj2nid((ASN1_OBJECT *)*sfld);
|
||||
} else {
|
||||
selector = ASN1_INTEGER_get((ASN1_INTEGER *)*sfld);
|
||||
}
|
||||
|
||||
/* Try to find matching entry in table Maybe should check application types
|
||||
* first to allow application override? Might also be useful to have a flag
|
||||
* which indicates table is sorted and we can do a binary search. For now
|
||||
* stick to a linear search. */
|
||||
|
||||
for (atbl = adb->tbl, i = 0; i < adb->tblcount; i++, atbl++) {
|
||||
if (atbl->value == selector) {
|
||||
return &atbl->tt;
|
||||
}
|
||||
}
|
||||
|
||||
/* FIXME: need to search application table too */
|
||||
|
||||
/* No match, return default type */
|
||||
if (!adb->default_tt) {
|
||||
goto err;
|
||||
}
|
||||
return adb->default_tt;
|
||||
|
||||
err:
|
||||
/* FIXME: should log the value or OID of unsupported type */
|
||||
if (nullerr) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_UNSUPPORTED_ANY_DEFINED_BY_TYPE);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
+206
@@ -0,0 +1,206 @@
|
||||
/* Written by Richard Levitte ([email protected]) for the OpenSSL
|
||||
* project 2001.
|
||||
* Written by Dr Stephen N Henson ([email protected]) for the OpenSSL
|
||||
* project 2008.
|
||||
*/
|
||||
/* ====================================================================
|
||||
* Copyright (c) 2001 The OpenSSL Project. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* 3. All advertising materials mentioning features or use of this
|
||||
* software must display the following acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
|
||||
*
|
||||
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
|
||||
* endorse or promote products derived from this software without
|
||||
* prior written permission. For written permission, please contact
|
||||
* [email protected].
|
||||
*
|
||||
* 5. Products derived from this software may not be called "OpenSSL"
|
||||
* nor may "OpenSSL" appear in their names without prior written
|
||||
* permission of the OpenSSL Project.
|
||||
*
|
||||
* 6. Redistributions of any form whatsoever must retain the following
|
||||
* acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
|
||||
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
|
||||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ====================================================================
|
||||
*
|
||||
* This product includes cryptographic software written by Eric Young
|
||||
* ([email protected]). This product includes software written by Tim
|
||||
* Hudson ([email protected]). */
|
||||
|
||||
#if !defined(_POSIX_C_SOURCE)
|
||||
#define _POSIX_C_SOURCE 201410L /* for gmtime_r */
|
||||
#endif
|
||||
|
||||
#include "asn1_locl.h"
|
||||
|
||||
#include <time.h>
|
||||
|
||||
|
||||
#define SECS_PER_DAY (24 * 60 * 60)
|
||||
|
||||
struct tm *OPENSSL_gmtime(const time_t *time, struct tm *result) {
|
||||
#if defined(OPENSSL_WINDOWS)
|
||||
if (gmtime_s(result, time)) {
|
||||
return NULL;
|
||||
}
|
||||
return result;
|
||||
#else
|
||||
return gmtime_r(time, result);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Convert date to and from julian day Uses Fliegel & Van Flandern algorithm */
|
||||
static long date_to_julian(int y, int m, int d) {
|
||||
return (1461 * (y + 4800 + (m - 14) / 12)) / 4 +
|
||||
(367 * (m - 2 - 12 * ((m - 14) / 12))) / 12 -
|
||||
(3 * ((y + 4900 + (m - 14) / 12) / 100)) / 4 + d - 32075;
|
||||
}
|
||||
|
||||
static void julian_to_date(long jd, int *y, int *m, int *d) {
|
||||
long L = jd + 68569;
|
||||
long n = (4 * L) / 146097;
|
||||
long i, j;
|
||||
|
||||
L = L - (146097 * n + 3) / 4;
|
||||
i = (4000 * (L + 1)) / 1461001;
|
||||
L = L - (1461 * i) / 4 + 31;
|
||||
j = (80 * L) / 2447;
|
||||
*d = L - (2447 * j) / 80;
|
||||
L = j / 11;
|
||||
*m = j + 2 - (12 * L);
|
||||
*y = 100 * (n - 49) + i + L;
|
||||
}
|
||||
|
||||
/* Convert tm structure and offset into julian day and seconds */
|
||||
static int julian_adj(const struct tm *tm, int off_day, long offset_sec,
|
||||
long *pday, int *psec) {
|
||||
int offset_hms, offset_day;
|
||||
long time_jd;
|
||||
int time_year, time_month, time_day;
|
||||
/* split offset into days and day seconds */
|
||||
offset_day = offset_sec / SECS_PER_DAY;
|
||||
/* Avoid sign issues with % operator */
|
||||
offset_hms = offset_sec - (offset_day * SECS_PER_DAY);
|
||||
offset_day += off_day;
|
||||
/* Add current time seconds to offset */
|
||||
offset_hms += tm->tm_hour * 3600 + tm->tm_min * 60 + tm->tm_sec;
|
||||
/* Adjust day seconds if overflow */
|
||||
if (offset_hms >= SECS_PER_DAY) {
|
||||
offset_day++;
|
||||
offset_hms -= SECS_PER_DAY;
|
||||
} else if (offset_hms < 0) {
|
||||
offset_day--;
|
||||
offset_hms += SECS_PER_DAY;
|
||||
}
|
||||
|
||||
/* Convert date of time structure into a Julian day number. */
|
||||
|
||||
time_year = tm->tm_year + 1900;
|
||||
time_month = tm->tm_mon + 1;
|
||||
time_day = tm->tm_mday;
|
||||
|
||||
time_jd = date_to_julian(time_year, time_month, time_day);
|
||||
|
||||
/* Work out Julian day of new date */
|
||||
time_jd += offset_day;
|
||||
|
||||
if (time_jd < 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
*pday = time_jd;
|
||||
*psec = offset_hms;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int OPENSSL_gmtime_adj(struct tm *tm, int off_day, long offset_sec) {
|
||||
int time_sec, time_year, time_month, time_day;
|
||||
long time_jd;
|
||||
|
||||
/* Convert time and offset into julian day and seconds */
|
||||
if (!julian_adj(tm, off_day, offset_sec, &time_jd, &time_sec)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Convert Julian day back to date */
|
||||
|
||||
julian_to_date(time_jd, &time_year, &time_month, &time_day);
|
||||
|
||||
if (time_year < 1900 || time_year > 9999) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Update tm structure */
|
||||
|
||||
tm->tm_year = time_year - 1900;
|
||||
tm->tm_mon = time_month - 1;
|
||||
tm->tm_mday = time_day;
|
||||
|
||||
tm->tm_hour = time_sec / 3600;
|
||||
tm->tm_min = (time_sec / 60) % 60;
|
||||
tm->tm_sec = time_sec % 60;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int OPENSSL_gmtime_diff(int *out_days, int *out_secs, const struct tm *from,
|
||||
const struct tm *to) {
|
||||
int from_sec, to_sec, diff_sec;
|
||||
long from_jd, to_jd, diff_day;
|
||||
|
||||
if (!julian_adj(from, 0, 0, &from_jd, &from_sec)) {
|
||||
return 0;
|
||||
}
|
||||
if (!julian_adj(to, 0, 0, &to_jd, &to_sec)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
diff_day = to_jd - from_jd;
|
||||
diff_sec = to_sec - from_sec;
|
||||
/* Adjust differences so both positive or both negative */
|
||||
if (diff_day > 0 && diff_sec < 0) {
|
||||
diff_day--;
|
||||
diff_sec += SECS_PER_DAY;
|
||||
}
|
||||
if (diff_day < 0 && diff_sec > 0) {
|
||||
diff_day++;
|
||||
diff_sec -= SECS_PER_DAY;
|
||||
}
|
||||
|
||||
if (out_days) {
|
||||
*out_days = (int)diff_day;
|
||||
}
|
||||
if (out_secs) {
|
||||
*out_secs = diff_sec;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -0,0 +1,206 @@
|
||||
/* Written by Richard Levitte ([email protected]) for the OpenSSL
|
||||
* project 2001.
|
||||
* Written by Dr Stephen N Henson ([email protected]) for the OpenSSL
|
||||
* project 2008.
|
||||
*/
|
||||
/* ====================================================================
|
||||
* Copyright (c) 2001 The OpenSSL Project. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* 3. All advertising materials mentioning features or use of this
|
||||
* software must display the following acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
|
||||
*
|
||||
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
|
||||
* endorse or promote products derived from this software without
|
||||
* prior written permission. For written permission, please contact
|
||||
* [email protected].
|
||||
*
|
||||
* 5. Products derived from this software may not be called "OpenSSL"
|
||||
* nor may "OpenSSL" appear in their names without prior written
|
||||
* permission of the OpenSSL Project.
|
||||
*
|
||||
* 6. Redistributions of any form whatsoever must retain the following
|
||||
* acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
|
||||
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
|
||||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ====================================================================
|
||||
*
|
||||
* This product includes cryptographic software written by Eric Young
|
||||
* ([email protected]). This product includes software written by Tim
|
||||
* Hudson ([email protected]). */
|
||||
|
||||
#if !defined(_POSIX_C_SOURCE)
|
||||
#define _POSIX_C_SOURCE 201410L /* for gmtime_r */
|
||||
#endif
|
||||
|
||||
#include "asn1_locl.h"
|
||||
|
||||
#include <time.h>
|
||||
|
||||
|
||||
#define SECS_PER_DAY (24 * 60 * 60)
|
||||
|
||||
struct tm *OPENSSL_gmtime(const time_t *time, struct tm *result) {
|
||||
#if defined(OPENSSL_WINDOWS)
|
||||
if (gmtime_s(result, time)) {
|
||||
return NULL;
|
||||
}
|
||||
return result;
|
||||
#else
|
||||
return gmtime_r(time, result);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Convert date to and from julian day Uses Fliegel & Van Flandern algorithm */
|
||||
static long date_to_julian(int y, int m, int d) {
|
||||
return (1461 * (y + 4800 + (m - 14) / 12)) / 4 +
|
||||
(367 * (m - 2 - 12 * ((m - 14) / 12))) / 12 -
|
||||
(3 * ((y + 4900 + (m - 14) / 12) / 100)) / 4 + d - 32075;
|
||||
}
|
||||
|
||||
static void julian_to_date(long jd, int *y, int *m, int *d) {
|
||||
long L = jd + 68569;
|
||||
long n = (4 * L) / 146097;
|
||||
long i, j;
|
||||
|
||||
L = L - (146097 * n + 3) / 4;
|
||||
i = (4000 * (L + 1)) / 1461001;
|
||||
L = L - (1461 * i) / 4 + 31;
|
||||
j = (80 * L) / 2447;
|
||||
*d = L - (2447 * j) / 80;
|
||||
L = j / 11;
|
||||
*m = j + 2 - (12 * L);
|
||||
*y = 100 * (n - 49) + i + L;
|
||||
}
|
||||
|
||||
/* Convert tm structure and offset into julian day and seconds */
|
||||
static int julian_adj(const struct tm *tm, int off_day, long offset_sec,
|
||||
long *pday, int *psec) {
|
||||
int offset_hms, offset_day;
|
||||
long time_jd;
|
||||
int time_year, time_month, time_day;
|
||||
/* split offset into days and day seconds */
|
||||
offset_day = offset_sec / SECS_PER_DAY;
|
||||
/* Avoid sign issues with % operator */
|
||||
offset_hms = offset_sec - (offset_day * SECS_PER_DAY);
|
||||
offset_day += off_day;
|
||||
/* Add current time seconds to offset */
|
||||
offset_hms += tm->tm_hour * 3600 + tm->tm_min * 60 + tm->tm_sec;
|
||||
/* Adjust day seconds if overflow */
|
||||
if (offset_hms >= SECS_PER_DAY) {
|
||||
offset_day++;
|
||||
offset_hms -= SECS_PER_DAY;
|
||||
} else if (offset_hms < 0) {
|
||||
offset_day--;
|
||||
offset_hms += SECS_PER_DAY;
|
||||
}
|
||||
|
||||
/* Convert date of time structure into a Julian day number. */
|
||||
|
||||
time_year = tm->tm_year + 1900;
|
||||
time_month = tm->tm_mon + 1;
|
||||
time_day = tm->tm_mday;
|
||||
|
||||
time_jd = date_to_julian(time_year, time_month, time_day);
|
||||
|
||||
/* Work out Julian day of new date */
|
||||
time_jd += offset_day;
|
||||
|
||||
if (time_jd < 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
*pday = time_jd;
|
||||
*psec = offset_hms;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int OPENSSL_gmtime_adj(struct tm *tm, int off_day, long offset_sec) {
|
||||
int time_sec, time_year, time_month, time_day;
|
||||
long time_jd;
|
||||
|
||||
/* Convert time and offset into julian day and seconds */
|
||||
if (!julian_adj(tm, off_day, offset_sec, &time_jd, &time_sec)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Convert Julian day back to date */
|
||||
|
||||
julian_to_date(time_jd, &time_year, &time_month, &time_day);
|
||||
|
||||
if (time_year < 1900 || time_year > 9999) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Update tm structure */
|
||||
|
||||
tm->tm_year = time_year - 1900;
|
||||
tm->tm_mon = time_month - 1;
|
||||
tm->tm_mday = time_day;
|
||||
|
||||
tm->tm_hour = time_sec / 3600;
|
||||
tm->tm_min = (time_sec / 60) % 60;
|
||||
tm->tm_sec = time_sec % 60;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int OPENSSL_gmtime_diff(int *out_days, int *out_secs, const struct tm *from,
|
||||
const struct tm *to) {
|
||||
int from_sec, to_sec, diff_sec;
|
||||
long from_jd, to_jd, diff_day;
|
||||
|
||||
if (!julian_adj(from, 0, 0, &from_jd, &from_sec)) {
|
||||
return 0;
|
||||
}
|
||||
if (!julian_adj(to, 0, 0, &to_jd, &to_sec)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
diff_day = to_jd - from_jd;
|
||||
diff_sec = to_sec - from_sec;
|
||||
/* Adjust differences so both positive or both negative */
|
||||
if (diff_day > 0 && diff_sec < 0) {
|
||||
diff_day--;
|
||||
diff_sec += SECS_PER_DAY;
|
||||
}
|
||||
if (diff_day < 0 && diff_sec > 0) {
|
||||
diff_day++;
|
||||
diff_sec -= SECS_PER_DAY;
|
||||
}
|
||||
|
||||
if (out_days) {
|
||||
*out_days = (int)diff_day;
|
||||
}
|
||||
if (out_secs) {
|
||||
*out_secs = diff_sec;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
+466
@@ -0,0 +1,466 @@
|
||||
/* Copyright (C) 1995-1998 Eric Young ([email protected])
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young ([email protected]).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson ([email protected]).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young ([email protected])"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson ([email protected])"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.] */
|
||||
|
||||
#include <openssl_grpc/base64.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <limits.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <openssl_grpc/type_check.h>
|
||||
|
||||
#include "../internal.h"
|
||||
|
||||
|
||||
// constant_time_lt_args_8 behaves like |constant_time_lt_8| but takes |uint8_t|
|
||||
// arguments for a slightly simpler implementation.
|
||||
static inline uint8_t constant_time_lt_args_8(uint8_t a, uint8_t b) {
|
||||
crypto_word_t aw = a;
|
||||
crypto_word_t bw = b;
|
||||
// |crypto_word_t| is larger than |uint8_t|, so |aw| and |bw| have the same
|
||||
// MSB. |aw| < |bw| iff MSB(|aw| - |bw|) is 1.
|
||||
return constant_time_msb_w(aw - bw);
|
||||
}
|
||||
|
||||
// constant_time_in_range_8 returns |CONSTTIME_TRUE_8| if |min| <= |a| <= |max|
|
||||
// and |CONSTTIME_FALSE_8| otherwise.
|
||||
static inline uint8_t constant_time_in_range_8(uint8_t a, uint8_t min,
|
||||
uint8_t max) {
|
||||
a -= min;
|
||||
return constant_time_lt_args_8(a, max - min + 1);
|
||||
}
|
||||
|
||||
// Encoding.
|
||||
|
||||
static uint8_t conv_bin2ascii(uint8_t a) {
|
||||
// Since PEM is sometimes used to carry private keys, we encode base64 data
|
||||
// itself in constant-time.
|
||||
a &= 0x3f;
|
||||
uint8_t ret = constant_time_select_8(constant_time_eq_8(a, 62), '+', '/');
|
||||
ret =
|
||||
constant_time_select_8(constant_time_lt_args_8(a, 62), a - 52 + '0', ret);
|
||||
ret =
|
||||
constant_time_select_8(constant_time_lt_args_8(a, 52), a - 26 + 'a', ret);
|
||||
ret = constant_time_select_8(constant_time_lt_args_8(a, 26), a + 'A', ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
OPENSSL_STATIC_ASSERT(sizeof(((EVP_ENCODE_CTX *)(NULL))->data) % 3 == 0,
|
||||
"data length must be a multiple of base64 chunk size");
|
||||
|
||||
int EVP_EncodedLength(size_t *out_len, size_t len) {
|
||||
if (len + 2 < len) {
|
||||
return 0;
|
||||
}
|
||||
len += 2;
|
||||
len /= 3;
|
||||
|
||||
if (((len << 2) >> 2) != len) {
|
||||
return 0;
|
||||
}
|
||||
len <<= 2;
|
||||
|
||||
if (len + 1 < len) {
|
||||
return 0;
|
||||
}
|
||||
len++;
|
||||
|
||||
*out_len = len;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void EVP_EncodeInit(EVP_ENCODE_CTX *ctx) {
|
||||
OPENSSL_memset(ctx, 0, sizeof(EVP_ENCODE_CTX));
|
||||
}
|
||||
|
||||
void EVP_EncodeUpdate(EVP_ENCODE_CTX *ctx, uint8_t *out, int *out_len,
|
||||
const uint8_t *in, size_t in_len) {
|
||||
size_t total = 0;
|
||||
|
||||
*out_len = 0;
|
||||
if (in_len == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
assert(ctx->data_used < sizeof(ctx->data));
|
||||
|
||||
if (sizeof(ctx->data) - ctx->data_used > in_len) {
|
||||
OPENSSL_memcpy(&ctx->data[ctx->data_used], in, in_len);
|
||||
ctx->data_used += (unsigned)in_len;
|
||||
return;
|
||||
}
|
||||
|
||||
if (ctx->data_used != 0) {
|
||||
const size_t todo = sizeof(ctx->data) - ctx->data_used;
|
||||
OPENSSL_memcpy(&ctx->data[ctx->data_used], in, todo);
|
||||
in += todo;
|
||||
in_len -= todo;
|
||||
|
||||
size_t encoded = EVP_EncodeBlock(out, ctx->data, sizeof(ctx->data));
|
||||
ctx->data_used = 0;
|
||||
|
||||
out += encoded;
|
||||
*(out++) = '\n';
|
||||
*out = '\0';
|
||||
|
||||
total = encoded + 1;
|
||||
}
|
||||
|
||||
while (in_len >= sizeof(ctx->data)) {
|
||||
size_t encoded = EVP_EncodeBlock(out, in, sizeof(ctx->data));
|
||||
in += sizeof(ctx->data);
|
||||
in_len -= sizeof(ctx->data);
|
||||
|
||||
out += encoded;
|
||||
*(out++) = '\n';
|
||||
*out = '\0';
|
||||
|
||||
if (total + encoded + 1 < total) {
|
||||
*out_len = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
total += encoded + 1;
|
||||
}
|
||||
|
||||
if (in_len != 0) {
|
||||
OPENSSL_memcpy(ctx->data, in, in_len);
|
||||
}
|
||||
|
||||
ctx->data_used = (unsigned)in_len;
|
||||
|
||||
if (total > INT_MAX) {
|
||||
// We cannot signal an error, but we can at least avoid making *out_len
|
||||
// negative.
|
||||
total = 0;
|
||||
}
|
||||
*out_len = (int)total;
|
||||
}
|
||||
|
||||
void EVP_EncodeFinal(EVP_ENCODE_CTX *ctx, uint8_t *out, int *out_len) {
|
||||
if (ctx->data_used == 0) {
|
||||
*out_len = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
size_t encoded = EVP_EncodeBlock(out, ctx->data, ctx->data_used);
|
||||
out[encoded++] = '\n';
|
||||
out[encoded] = '\0';
|
||||
ctx->data_used = 0;
|
||||
|
||||
// ctx->data_used is bounded by sizeof(ctx->data), so this does not
|
||||
// overflow.
|
||||
assert(encoded <= INT_MAX);
|
||||
*out_len = (int)encoded;
|
||||
}
|
||||
|
||||
size_t EVP_EncodeBlock(uint8_t *dst, const uint8_t *src, size_t src_len) {
|
||||
uint32_t l;
|
||||
size_t remaining = src_len, ret = 0;
|
||||
|
||||
while (remaining) {
|
||||
if (remaining >= 3) {
|
||||
l = (((uint32_t)src[0]) << 16L) | (((uint32_t)src[1]) << 8L) | src[2];
|
||||
*(dst++) = conv_bin2ascii(l >> 18L);
|
||||
*(dst++) = conv_bin2ascii(l >> 12L);
|
||||
*(dst++) = conv_bin2ascii(l >> 6L);
|
||||
*(dst++) = conv_bin2ascii(l);
|
||||
remaining -= 3;
|
||||
} else {
|
||||
l = ((uint32_t)src[0]) << 16L;
|
||||
if (remaining == 2) {
|
||||
l |= ((uint32_t)src[1] << 8L);
|
||||
}
|
||||
|
||||
*(dst++) = conv_bin2ascii(l >> 18L);
|
||||
*(dst++) = conv_bin2ascii(l >> 12L);
|
||||
*(dst++) = (remaining == 1) ? '=' : conv_bin2ascii(l >> 6L);
|
||||
*(dst++) = '=';
|
||||
remaining = 0;
|
||||
}
|
||||
ret += 4;
|
||||
src += 3;
|
||||
}
|
||||
|
||||
*dst = '\0';
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
// Decoding.
|
||||
|
||||
int EVP_DecodedLength(size_t *out_len, size_t len) {
|
||||
if (len % 4 != 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
*out_len = (len / 4) * 3;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void EVP_DecodeInit(EVP_ENCODE_CTX *ctx) {
|
||||
OPENSSL_memset(ctx, 0, sizeof(EVP_ENCODE_CTX));
|
||||
}
|
||||
|
||||
static uint8_t base64_ascii_to_bin(uint8_t a) {
|
||||
// Since PEM is sometimes used to carry private keys, we decode base64 data
|
||||
// itself in constant-time.
|
||||
const uint8_t is_upper = constant_time_in_range_8(a, 'A', 'Z');
|
||||
const uint8_t is_lower = constant_time_in_range_8(a, 'a', 'z');
|
||||
const uint8_t is_digit = constant_time_in_range_8(a, '0', '9');
|
||||
const uint8_t is_plus = constant_time_eq_8(a, '+');
|
||||
const uint8_t is_slash = constant_time_eq_8(a, '/');
|
||||
const uint8_t is_equals = constant_time_eq_8(a, '=');
|
||||
|
||||
uint8_t ret = 0xff; // 0xff signals invalid.
|
||||
ret = constant_time_select_8(is_upper, a - 'A', ret); // [0,26)
|
||||
ret = constant_time_select_8(is_lower, a - 'a' + 26, ret); // [26,52)
|
||||
ret = constant_time_select_8(is_digit, a - '0' + 52, ret); // [52,62)
|
||||
ret = constant_time_select_8(is_plus, 62, ret);
|
||||
ret = constant_time_select_8(is_slash, 63, ret);
|
||||
// Padding maps to zero, to be further handled by the caller.
|
||||
ret = constant_time_select_8(is_equals, 0, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
// base64_decode_quad decodes a single “quad” (i.e. four characters) of base64
|
||||
// data and writes up to three bytes to |out|. It sets |*out_num_bytes| to the
|
||||
// number of bytes written, which will be less than three if the quad ended
|
||||
// with padding. It returns one on success or zero on error.
|
||||
static int base64_decode_quad(uint8_t *out, size_t *out_num_bytes,
|
||||
const uint8_t *in) {
|
||||
const uint8_t a = base64_ascii_to_bin(in[0]);
|
||||
const uint8_t b = base64_ascii_to_bin(in[1]);
|
||||
const uint8_t c = base64_ascii_to_bin(in[2]);
|
||||
const uint8_t d = base64_ascii_to_bin(in[3]);
|
||||
if (a == 0xff || b == 0xff || c == 0xff || d == 0xff) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
const uint32_t v = ((uint32_t)a) << 18 | ((uint32_t)b) << 12 |
|
||||
((uint32_t)c) << 6 | (uint32_t)d;
|
||||
|
||||
const unsigned padding_pattern = (in[0] == '=') << 3 |
|
||||
(in[1] == '=') << 2 |
|
||||
(in[2] == '=') << 1 |
|
||||
(in[3] == '=');
|
||||
|
||||
switch (padding_pattern) {
|
||||
case 0:
|
||||
// The common case of no padding.
|
||||
*out_num_bytes = 3;
|
||||
out[0] = v >> 16;
|
||||
out[1] = v >> 8;
|
||||
out[2] = v;
|
||||
break;
|
||||
|
||||
case 1: // xxx=
|
||||
*out_num_bytes = 2;
|
||||
out[0] = v >> 16;
|
||||
out[1] = v >> 8;
|
||||
break;
|
||||
|
||||
case 3: // xx==
|
||||
*out_num_bytes = 1;
|
||||
out[0] = v >> 16;
|
||||
break;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int EVP_DecodeUpdate(EVP_ENCODE_CTX *ctx, uint8_t *out, int *out_len,
|
||||
const uint8_t *in, size_t in_len) {
|
||||
*out_len = 0;
|
||||
|
||||
if (ctx->error_encountered) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
size_t bytes_out = 0, i;
|
||||
for (i = 0; i < in_len; i++) {
|
||||
const char c = in[i];
|
||||
switch (c) {
|
||||
case ' ':
|
||||
case '\t':
|
||||
case '\r':
|
||||
case '\n':
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ctx->eof_seen) {
|
||||
ctx->error_encountered = 1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
ctx->data[ctx->data_used++] = c;
|
||||
if (ctx->data_used == 4) {
|
||||
size_t num_bytes_resulting;
|
||||
if (!base64_decode_quad(out, &num_bytes_resulting, ctx->data)) {
|
||||
ctx->error_encountered = 1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
ctx->data_used = 0;
|
||||
bytes_out += num_bytes_resulting;
|
||||
out += num_bytes_resulting;
|
||||
|
||||
if (num_bytes_resulting < 3) {
|
||||
ctx->eof_seen = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (bytes_out > INT_MAX) {
|
||||
ctx->error_encountered = 1;
|
||||
*out_len = 0;
|
||||
return -1;
|
||||
}
|
||||
*out_len = (int)bytes_out;
|
||||
|
||||
if (ctx->eof_seen) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int EVP_DecodeFinal(EVP_ENCODE_CTX *ctx, uint8_t *out, int *out_len) {
|
||||
*out_len = 0;
|
||||
if (ctx->error_encountered || ctx->data_used != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int EVP_DecodeBase64(uint8_t *out, size_t *out_len, size_t max_out,
|
||||
const uint8_t *in, size_t in_len) {
|
||||
*out_len = 0;
|
||||
|
||||
if (in_len % 4 != 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t max_len;
|
||||
if (!EVP_DecodedLength(&max_len, in_len) ||
|
||||
max_out < max_len) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t i, bytes_out = 0;
|
||||
for (i = 0; i < in_len; i += 4) {
|
||||
size_t num_bytes_resulting;
|
||||
|
||||
if (!base64_decode_quad(out, &num_bytes_resulting, &in[i])) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
bytes_out += num_bytes_resulting;
|
||||
out += num_bytes_resulting;
|
||||
if (num_bytes_resulting != 3 && i != in_len - 4) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
*out_len = bytes_out;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int EVP_DecodeBlock(uint8_t *dst, const uint8_t *src, size_t src_len) {
|
||||
// Trim spaces and tabs from the beginning of the input.
|
||||
while (src_len > 0) {
|
||||
if (src[0] != ' ' && src[0] != '\t') {
|
||||
break;
|
||||
}
|
||||
|
||||
src++;
|
||||
src_len--;
|
||||
}
|
||||
|
||||
// Trim newlines, spaces and tabs from the end of the line.
|
||||
while (src_len > 0) {
|
||||
switch (src[src_len-1]) {
|
||||
case ' ':
|
||||
case '\t':
|
||||
case '\r':
|
||||
case '\n':
|
||||
src_len--;
|
||||
continue;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
size_t dst_len;
|
||||
if (!EVP_DecodedLength(&dst_len, src_len) ||
|
||||
dst_len > INT_MAX ||
|
||||
!EVP_DecodeBase64(dst, &dst_len, dst_len, src, src_len)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// EVP_DecodeBlock does not take padding into account, so put the
|
||||
// NULs back in... so the caller can strip them back out.
|
||||
while (dst_len % 3 != 0) {
|
||||
dst[dst_len++] = '\0';
|
||||
}
|
||||
assert(dst_len <= INT_MAX);
|
||||
|
||||
return (int)dst_len;
|
||||
}
|
||||
@@ -0,0 +1,466 @@
|
||||
/* Copyright (C) 1995-1998 Eric Young ([email protected])
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young ([email protected]).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson ([email protected]).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young ([email protected])"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson ([email protected])"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.] */
|
||||
|
||||
#include <openssl/base64.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <limits.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <openssl/type_check.h>
|
||||
|
||||
#include "../internal.h"
|
||||
|
||||
|
||||
// constant_time_lt_args_8 behaves like |constant_time_lt_8| but takes |uint8_t|
|
||||
// arguments for a slightly simpler implementation.
|
||||
static inline uint8_t constant_time_lt_args_8(uint8_t a, uint8_t b) {
|
||||
crypto_word_t aw = a;
|
||||
crypto_word_t bw = b;
|
||||
// |crypto_word_t| is larger than |uint8_t|, so |aw| and |bw| have the same
|
||||
// MSB. |aw| < |bw| iff MSB(|aw| - |bw|) is 1.
|
||||
return constant_time_msb_w(aw - bw);
|
||||
}
|
||||
|
||||
// constant_time_in_range_8 returns |CONSTTIME_TRUE_8| if |min| <= |a| <= |max|
|
||||
// and |CONSTTIME_FALSE_8| otherwise.
|
||||
static inline uint8_t constant_time_in_range_8(uint8_t a, uint8_t min,
|
||||
uint8_t max) {
|
||||
a -= min;
|
||||
return constant_time_lt_args_8(a, max - min + 1);
|
||||
}
|
||||
|
||||
// Encoding.
|
||||
|
||||
static uint8_t conv_bin2ascii(uint8_t a) {
|
||||
// Since PEM is sometimes used to carry private keys, we encode base64 data
|
||||
// itself in constant-time.
|
||||
a &= 0x3f;
|
||||
uint8_t ret = constant_time_select_8(constant_time_eq_8(a, 62), '+', '/');
|
||||
ret =
|
||||
constant_time_select_8(constant_time_lt_args_8(a, 62), a - 52 + '0', ret);
|
||||
ret =
|
||||
constant_time_select_8(constant_time_lt_args_8(a, 52), a - 26 + 'a', ret);
|
||||
ret = constant_time_select_8(constant_time_lt_args_8(a, 26), a + 'A', ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
OPENSSL_STATIC_ASSERT(sizeof(((EVP_ENCODE_CTX *)(NULL))->data) % 3 == 0,
|
||||
"data length must be a multiple of base64 chunk size");
|
||||
|
||||
int EVP_EncodedLength(size_t *out_len, size_t len) {
|
||||
if (len + 2 < len) {
|
||||
return 0;
|
||||
}
|
||||
len += 2;
|
||||
len /= 3;
|
||||
|
||||
if (((len << 2) >> 2) != len) {
|
||||
return 0;
|
||||
}
|
||||
len <<= 2;
|
||||
|
||||
if (len + 1 < len) {
|
||||
return 0;
|
||||
}
|
||||
len++;
|
||||
|
||||
*out_len = len;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void EVP_EncodeInit(EVP_ENCODE_CTX *ctx) {
|
||||
OPENSSL_memset(ctx, 0, sizeof(EVP_ENCODE_CTX));
|
||||
}
|
||||
|
||||
void EVP_EncodeUpdate(EVP_ENCODE_CTX *ctx, uint8_t *out, int *out_len,
|
||||
const uint8_t *in, size_t in_len) {
|
||||
size_t total = 0;
|
||||
|
||||
*out_len = 0;
|
||||
if (in_len == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
assert(ctx->data_used < sizeof(ctx->data));
|
||||
|
||||
if (sizeof(ctx->data) - ctx->data_used > in_len) {
|
||||
OPENSSL_memcpy(&ctx->data[ctx->data_used], in, in_len);
|
||||
ctx->data_used += (unsigned)in_len;
|
||||
return;
|
||||
}
|
||||
|
||||
if (ctx->data_used != 0) {
|
||||
const size_t todo = sizeof(ctx->data) - ctx->data_used;
|
||||
OPENSSL_memcpy(&ctx->data[ctx->data_used], in, todo);
|
||||
in += todo;
|
||||
in_len -= todo;
|
||||
|
||||
size_t encoded = EVP_EncodeBlock(out, ctx->data, sizeof(ctx->data));
|
||||
ctx->data_used = 0;
|
||||
|
||||
out += encoded;
|
||||
*(out++) = '\n';
|
||||
*out = '\0';
|
||||
|
||||
total = encoded + 1;
|
||||
}
|
||||
|
||||
while (in_len >= sizeof(ctx->data)) {
|
||||
size_t encoded = EVP_EncodeBlock(out, in, sizeof(ctx->data));
|
||||
in += sizeof(ctx->data);
|
||||
in_len -= sizeof(ctx->data);
|
||||
|
||||
out += encoded;
|
||||
*(out++) = '\n';
|
||||
*out = '\0';
|
||||
|
||||
if (total + encoded + 1 < total) {
|
||||
*out_len = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
total += encoded + 1;
|
||||
}
|
||||
|
||||
if (in_len != 0) {
|
||||
OPENSSL_memcpy(ctx->data, in, in_len);
|
||||
}
|
||||
|
||||
ctx->data_used = (unsigned)in_len;
|
||||
|
||||
if (total > INT_MAX) {
|
||||
// We cannot signal an error, but we can at least avoid making *out_len
|
||||
// negative.
|
||||
total = 0;
|
||||
}
|
||||
*out_len = (int)total;
|
||||
}
|
||||
|
||||
void EVP_EncodeFinal(EVP_ENCODE_CTX *ctx, uint8_t *out, int *out_len) {
|
||||
if (ctx->data_used == 0) {
|
||||
*out_len = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
size_t encoded = EVP_EncodeBlock(out, ctx->data, ctx->data_used);
|
||||
out[encoded++] = '\n';
|
||||
out[encoded] = '\0';
|
||||
ctx->data_used = 0;
|
||||
|
||||
// ctx->data_used is bounded by sizeof(ctx->data), so this does not
|
||||
// overflow.
|
||||
assert(encoded <= INT_MAX);
|
||||
*out_len = (int)encoded;
|
||||
}
|
||||
|
||||
size_t EVP_EncodeBlock(uint8_t *dst, const uint8_t *src, size_t src_len) {
|
||||
uint32_t l;
|
||||
size_t remaining = src_len, ret = 0;
|
||||
|
||||
while (remaining) {
|
||||
if (remaining >= 3) {
|
||||
l = (((uint32_t)src[0]) << 16L) | (((uint32_t)src[1]) << 8L) | src[2];
|
||||
*(dst++) = conv_bin2ascii(l >> 18L);
|
||||
*(dst++) = conv_bin2ascii(l >> 12L);
|
||||
*(dst++) = conv_bin2ascii(l >> 6L);
|
||||
*(dst++) = conv_bin2ascii(l);
|
||||
remaining -= 3;
|
||||
} else {
|
||||
l = ((uint32_t)src[0]) << 16L;
|
||||
if (remaining == 2) {
|
||||
l |= ((uint32_t)src[1] << 8L);
|
||||
}
|
||||
|
||||
*(dst++) = conv_bin2ascii(l >> 18L);
|
||||
*(dst++) = conv_bin2ascii(l >> 12L);
|
||||
*(dst++) = (remaining == 1) ? '=' : conv_bin2ascii(l >> 6L);
|
||||
*(dst++) = '=';
|
||||
remaining = 0;
|
||||
}
|
||||
ret += 4;
|
||||
src += 3;
|
||||
}
|
||||
|
||||
*dst = '\0';
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
// Decoding.
|
||||
|
||||
int EVP_DecodedLength(size_t *out_len, size_t len) {
|
||||
if (len % 4 != 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
*out_len = (len / 4) * 3;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void EVP_DecodeInit(EVP_ENCODE_CTX *ctx) {
|
||||
OPENSSL_memset(ctx, 0, sizeof(EVP_ENCODE_CTX));
|
||||
}
|
||||
|
||||
static uint8_t base64_ascii_to_bin(uint8_t a) {
|
||||
// Since PEM is sometimes used to carry private keys, we decode base64 data
|
||||
// itself in constant-time.
|
||||
const uint8_t is_upper = constant_time_in_range_8(a, 'A', 'Z');
|
||||
const uint8_t is_lower = constant_time_in_range_8(a, 'a', 'z');
|
||||
const uint8_t is_digit = constant_time_in_range_8(a, '0', '9');
|
||||
const uint8_t is_plus = constant_time_eq_8(a, '+');
|
||||
const uint8_t is_slash = constant_time_eq_8(a, '/');
|
||||
const uint8_t is_equals = constant_time_eq_8(a, '=');
|
||||
|
||||
uint8_t ret = 0xff; // 0xff signals invalid.
|
||||
ret = constant_time_select_8(is_upper, a - 'A', ret); // [0,26)
|
||||
ret = constant_time_select_8(is_lower, a - 'a' + 26, ret); // [26,52)
|
||||
ret = constant_time_select_8(is_digit, a - '0' + 52, ret); // [52,62)
|
||||
ret = constant_time_select_8(is_plus, 62, ret);
|
||||
ret = constant_time_select_8(is_slash, 63, ret);
|
||||
// Padding maps to zero, to be further handled by the caller.
|
||||
ret = constant_time_select_8(is_equals, 0, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
// base64_decode_quad decodes a single “quad” (i.e. four characters) of base64
|
||||
// data and writes up to three bytes to |out|. It sets |*out_num_bytes| to the
|
||||
// number of bytes written, which will be less than three if the quad ended
|
||||
// with padding. It returns one on success or zero on error.
|
||||
static int base64_decode_quad(uint8_t *out, size_t *out_num_bytes,
|
||||
const uint8_t *in) {
|
||||
const uint8_t a = base64_ascii_to_bin(in[0]);
|
||||
const uint8_t b = base64_ascii_to_bin(in[1]);
|
||||
const uint8_t c = base64_ascii_to_bin(in[2]);
|
||||
const uint8_t d = base64_ascii_to_bin(in[3]);
|
||||
if (a == 0xff || b == 0xff || c == 0xff || d == 0xff) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
const uint32_t v = ((uint32_t)a) << 18 | ((uint32_t)b) << 12 |
|
||||
((uint32_t)c) << 6 | (uint32_t)d;
|
||||
|
||||
const unsigned padding_pattern = (in[0] == '=') << 3 |
|
||||
(in[1] == '=') << 2 |
|
||||
(in[2] == '=') << 1 |
|
||||
(in[3] == '=');
|
||||
|
||||
switch (padding_pattern) {
|
||||
case 0:
|
||||
// The common case of no padding.
|
||||
*out_num_bytes = 3;
|
||||
out[0] = v >> 16;
|
||||
out[1] = v >> 8;
|
||||
out[2] = v;
|
||||
break;
|
||||
|
||||
case 1: // xxx=
|
||||
*out_num_bytes = 2;
|
||||
out[0] = v >> 16;
|
||||
out[1] = v >> 8;
|
||||
break;
|
||||
|
||||
case 3: // xx==
|
||||
*out_num_bytes = 1;
|
||||
out[0] = v >> 16;
|
||||
break;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int EVP_DecodeUpdate(EVP_ENCODE_CTX *ctx, uint8_t *out, int *out_len,
|
||||
const uint8_t *in, size_t in_len) {
|
||||
*out_len = 0;
|
||||
|
||||
if (ctx->error_encountered) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
size_t bytes_out = 0, i;
|
||||
for (i = 0; i < in_len; i++) {
|
||||
const char c = in[i];
|
||||
switch (c) {
|
||||
case ' ':
|
||||
case '\t':
|
||||
case '\r':
|
||||
case '\n':
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ctx->eof_seen) {
|
||||
ctx->error_encountered = 1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
ctx->data[ctx->data_used++] = c;
|
||||
if (ctx->data_used == 4) {
|
||||
size_t num_bytes_resulting;
|
||||
if (!base64_decode_quad(out, &num_bytes_resulting, ctx->data)) {
|
||||
ctx->error_encountered = 1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
ctx->data_used = 0;
|
||||
bytes_out += num_bytes_resulting;
|
||||
out += num_bytes_resulting;
|
||||
|
||||
if (num_bytes_resulting < 3) {
|
||||
ctx->eof_seen = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (bytes_out > INT_MAX) {
|
||||
ctx->error_encountered = 1;
|
||||
*out_len = 0;
|
||||
return -1;
|
||||
}
|
||||
*out_len = (int)bytes_out;
|
||||
|
||||
if (ctx->eof_seen) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int EVP_DecodeFinal(EVP_ENCODE_CTX *ctx, uint8_t *out, int *out_len) {
|
||||
*out_len = 0;
|
||||
if (ctx->error_encountered || ctx->data_used != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int EVP_DecodeBase64(uint8_t *out, size_t *out_len, size_t max_out,
|
||||
const uint8_t *in, size_t in_len) {
|
||||
*out_len = 0;
|
||||
|
||||
if (in_len % 4 != 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t max_len;
|
||||
if (!EVP_DecodedLength(&max_len, in_len) ||
|
||||
max_out < max_len) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t i, bytes_out = 0;
|
||||
for (i = 0; i < in_len; i += 4) {
|
||||
size_t num_bytes_resulting;
|
||||
|
||||
if (!base64_decode_quad(out, &num_bytes_resulting, &in[i])) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
bytes_out += num_bytes_resulting;
|
||||
out += num_bytes_resulting;
|
||||
if (num_bytes_resulting != 3 && i != in_len - 4) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
*out_len = bytes_out;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int EVP_DecodeBlock(uint8_t *dst, const uint8_t *src, size_t src_len) {
|
||||
// Trim spaces and tabs from the beginning of the input.
|
||||
while (src_len > 0) {
|
||||
if (src[0] != ' ' && src[0] != '\t') {
|
||||
break;
|
||||
}
|
||||
|
||||
src++;
|
||||
src_len--;
|
||||
}
|
||||
|
||||
// Trim newlines, spaces and tabs from the end of the line.
|
||||
while (src_len > 0) {
|
||||
switch (src[src_len-1]) {
|
||||
case ' ':
|
||||
case '\t':
|
||||
case '\r':
|
||||
case '\n':
|
||||
src_len--;
|
||||
continue;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
size_t dst_len;
|
||||
if (!EVP_DecodedLength(&dst_len, src_len) ||
|
||||
dst_len > INT_MAX ||
|
||||
!EVP_DecodeBase64(dst, &dst_len, dst_len, src, src_len)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// EVP_DecodeBlock does not take padding into account, so put the
|
||||
// NULs back in... so the caller can strip them back out.
|
||||
while (dst_len % 3 != 0) {
|
||||
dst[dst_len++] = '\0';
|
||||
}
|
||||
assert(dst_len <= INT_MAX);
|
||||
|
||||
return (int)dst_len;
|
||||
}
|
||||
Generated
+700
@@ -0,0 +1,700 @@
|
||||
/* Copyright (C) 1995-1998 Eric Young ([email protected])
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young ([email protected]).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson ([email protected]).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young ([email protected])"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson ([email protected])"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.] */
|
||||
|
||||
#include <openssl_grpc/bio.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <openssl_grpc/asn1.h>
|
||||
#include <openssl_grpc/err.h>
|
||||
#include <openssl_grpc/mem.h>
|
||||
#include <openssl_grpc/thread.h>
|
||||
|
||||
#include "../internal.h"
|
||||
|
||||
|
||||
BIO *BIO_new(const BIO_METHOD *method) {
|
||||
BIO *ret = OPENSSL_malloc(sizeof(BIO));
|
||||
if (ret == NULL) {
|
||||
OPENSSL_PUT_ERROR(BIO, ERR_R_MALLOC_FAILURE);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
OPENSSL_memset(ret, 0, sizeof(BIO));
|
||||
ret->method = method;
|
||||
ret->shutdown = 1;
|
||||
ret->references = 1;
|
||||
|
||||
if (method->create != NULL && !method->create(ret)) {
|
||||
OPENSSL_free(ret);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int BIO_free(BIO *bio) {
|
||||
BIO *next_bio;
|
||||
|
||||
for (; bio != NULL; bio = next_bio) {
|
||||
if (!CRYPTO_refcount_dec_and_test_zero(&bio->references)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
next_bio = BIO_pop(bio);
|
||||
|
||||
if (bio->method != NULL && bio->method->destroy != NULL) {
|
||||
bio->method->destroy(bio);
|
||||
}
|
||||
|
||||
OPENSSL_free(bio);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int BIO_up_ref(BIO *bio) {
|
||||
CRYPTO_refcount_inc(&bio->references);
|
||||
return 1;
|
||||
}
|
||||
|
||||
void BIO_vfree(BIO *bio) {
|
||||
BIO_free(bio);
|
||||
}
|
||||
|
||||
void BIO_free_all(BIO *bio) {
|
||||
BIO_free(bio);
|
||||
}
|
||||
|
||||
int BIO_read(BIO *bio, void *buf, int len) {
|
||||
if (bio == NULL || bio->method == NULL || bio->method->bread == NULL) {
|
||||
OPENSSL_PUT_ERROR(BIO, BIO_R_UNSUPPORTED_METHOD);
|
||||
return -2;
|
||||
}
|
||||
if (!bio->init) {
|
||||
OPENSSL_PUT_ERROR(BIO, BIO_R_UNINITIALIZED);
|
||||
return -2;
|
||||
}
|
||||
if (len <= 0) {
|
||||
return 0;
|
||||
}
|
||||
int ret = bio->method->bread(bio, buf, len);
|
||||
if (ret > 0) {
|
||||
bio->num_read += ret;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int BIO_gets(BIO *bio, char *buf, int len) {
|
||||
if (bio == NULL || bio->method == NULL || bio->method->bgets == NULL) {
|
||||
OPENSSL_PUT_ERROR(BIO, BIO_R_UNSUPPORTED_METHOD);
|
||||
return -2;
|
||||
}
|
||||
if (!bio->init) {
|
||||
OPENSSL_PUT_ERROR(BIO, BIO_R_UNINITIALIZED);
|
||||
return -2;
|
||||
}
|
||||
if (len <= 0) {
|
||||
return 0;
|
||||
}
|
||||
int ret = bio->method->bgets(bio, buf, len);
|
||||
if (ret > 0) {
|
||||
bio->num_read += ret;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int BIO_write(BIO *bio, const void *in, int inl) {
|
||||
if (bio == NULL || bio->method == NULL || bio->method->bwrite == NULL) {
|
||||
OPENSSL_PUT_ERROR(BIO, BIO_R_UNSUPPORTED_METHOD);
|
||||
return -2;
|
||||
}
|
||||
if (!bio->init) {
|
||||
OPENSSL_PUT_ERROR(BIO, BIO_R_UNINITIALIZED);
|
||||
return -2;
|
||||
}
|
||||
if (inl <= 0) {
|
||||
return 0;
|
||||
}
|
||||
int ret = bio->method->bwrite(bio, in, inl);
|
||||
if (ret > 0) {
|
||||
bio->num_write += ret;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int BIO_write_all(BIO *bio, const void *data, size_t len) {
|
||||
const uint8_t *data_u8 = data;
|
||||
while (len > 0) {
|
||||
int ret = BIO_write(bio, data_u8, len > INT_MAX ? INT_MAX : (int)len);
|
||||
if (ret <= 0) {
|
||||
return 0;
|
||||
}
|
||||
data_u8 += ret;
|
||||
len -= ret;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int BIO_puts(BIO *bio, const char *in) {
|
||||
return BIO_write(bio, in, strlen(in));
|
||||
}
|
||||
|
||||
int BIO_flush(BIO *bio) {
|
||||
return BIO_ctrl(bio, BIO_CTRL_FLUSH, 0, NULL);
|
||||
}
|
||||
|
||||
long BIO_ctrl(BIO *bio, int cmd, long larg, void *parg) {
|
||||
if (bio == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (bio->method == NULL || bio->method->ctrl == NULL) {
|
||||
OPENSSL_PUT_ERROR(BIO, BIO_R_UNSUPPORTED_METHOD);
|
||||
return -2;
|
||||
}
|
||||
|
||||
return bio->method->ctrl(bio, cmd, larg, parg);
|
||||
}
|
||||
|
||||
char *BIO_ptr_ctrl(BIO *b, int cmd, long larg) {
|
||||
char *p = NULL;
|
||||
|
||||
if (BIO_ctrl(b, cmd, larg, (void *)&p) <= 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
long BIO_int_ctrl(BIO *b, int cmd, long larg, int iarg) {
|
||||
int i = iarg;
|
||||
|
||||
return BIO_ctrl(b, cmd, larg, (void *)&i);
|
||||
}
|
||||
|
||||
int BIO_reset(BIO *bio) {
|
||||
return BIO_ctrl(bio, BIO_CTRL_RESET, 0, NULL);
|
||||
}
|
||||
|
||||
int BIO_eof(BIO *bio) {
|
||||
return BIO_ctrl(bio, BIO_CTRL_EOF, 0, NULL);
|
||||
}
|
||||
|
||||
void BIO_set_flags(BIO *bio, int flags) {
|
||||
bio->flags |= flags;
|
||||
}
|
||||
|
||||
int BIO_test_flags(const BIO *bio, int flags) {
|
||||
return bio->flags & flags;
|
||||
}
|
||||
|
||||
int BIO_should_read(const BIO *bio) {
|
||||
return BIO_test_flags(bio, BIO_FLAGS_READ);
|
||||
}
|
||||
|
||||
int BIO_should_write(const BIO *bio) {
|
||||
return BIO_test_flags(bio, BIO_FLAGS_WRITE);
|
||||
}
|
||||
|
||||
int BIO_should_retry(const BIO *bio) {
|
||||
return BIO_test_flags(bio, BIO_FLAGS_SHOULD_RETRY);
|
||||
}
|
||||
|
||||
int BIO_should_io_special(const BIO *bio) {
|
||||
return BIO_test_flags(bio, BIO_FLAGS_IO_SPECIAL);
|
||||
}
|
||||
|
||||
int BIO_get_retry_reason(const BIO *bio) { return bio->retry_reason; }
|
||||
|
||||
void BIO_clear_flags(BIO *bio, int flags) {
|
||||
bio->flags &= ~flags;
|
||||
}
|
||||
|
||||
void BIO_set_retry_read(BIO *bio) {
|
||||
bio->flags |= BIO_FLAGS_READ | BIO_FLAGS_SHOULD_RETRY;
|
||||
}
|
||||
|
||||
void BIO_set_retry_write(BIO *bio) {
|
||||
bio->flags |= BIO_FLAGS_WRITE | BIO_FLAGS_SHOULD_RETRY;
|
||||
}
|
||||
|
||||
static const int kRetryFlags = BIO_FLAGS_RWS | BIO_FLAGS_SHOULD_RETRY;
|
||||
|
||||
int BIO_get_retry_flags(BIO *bio) {
|
||||
return bio->flags & kRetryFlags;
|
||||
}
|
||||
|
||||
void BIO_clear_retry_flags(BIO *bio) {
|
||||
bio->flags &= ~kRetryFlags;
|
||||
bio->retry_reason = 0;
|
||||
}
|
||||
|
||||
int BIO_method_type(const BIO *bio) { return bio->method->type; }
|
||||
|
||||
void BIO_copy_next_retry(BIO *bio) {
|
||||
BIO_clear_retry_flags(bio);
|
||||
BIO_set_flags(bio, BIO_get_retry_flags(bio->next_bio));
|
||||
bio->retry_reason = bio->next_bio->retry_reason;
|
||||
}
|
||||
|
||||
long BIO_callback_ctrl(BIO *bio, int cmd, bio_info_cb fp) {
|
||||
if (bio == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (bio->method == NULL || bio->method->callback_ctrl == NULL) {
|
||||
OPENSSL_PUT_ERROR(BIO, BIO_R_UNSUPPORTED_METHOD);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return bio->method->callback_ctrl(bio, cmd, fp);
|
||||
}
|
||||
|
||||
size_t BIO_pending(const BIO *bio) {
|
||||
const long r = BIO_ctrl((BIO *) bio, BIO_CTRL_PENDING, 0, NULL);
|
||||
assert(r >= 0);
|
||||
|
||||
if (r < 0) {
|
||||
return 0;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
size_t BIO_ctrl_pending(const BIO *bio) {
|
||||
return BIO_pending(bio);
|
||||
}
|
||||
|
||||
size_t BIO_wpending(const BIO *bio) {
|
||||
const long r = BIO_ctrl((BIO *) bio, BIO_CTRL_WPENDING, 0, NULL);
|
||||
assert(r >= 0);
|
||||
|
||||
if (r < 0) {
|
||||
return 0;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
int BIO_set_close(BIO *bio, int close_flag) {
|
||||
return BIO_ctrl(bio, BIO_CTRL_SET_CLOSE, close_flag, NULL);
|
||||
}
|
||||
|
||||
OPENSSL_EXPORT size_t BIO_number_read(const BIO *bio) {
|
||||
return bio->num_read;
|
||||
}
|
||||
|
||||
OPENSSL_EXPORT size_t BIO_number_written(const BIO *bio) {
|
||||
return bio->num_write;
|
||||
}
|
||||
|
||||
BIO *BIO_push(BIO *bio, BIO *appended_bio) {
|
||||
BIO *last_bio;
|
||||
|
||||
if (bio == NULL) {
|
||||
return bio;
|
||||
}
|
||||
|
||||
last_bio = bio;
|
||||
while (last_bio->next_bio != NULL) {
|
||||
last_bio = last_bio->next_bio;
|
||||
}
|
||||
|
||||
last_bio->next_bio = appended_bio;
|
||||
return bio;
|
||||
}
|
||||
|
||||
BIO *BIO_pop(BIO *bio) {
|
||||
BIO *ret;
|
||||
|
||||
if (bio == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
ret = bio->next_bio;
|
||||
bio->next_bio = NULL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
BIO *BIO_next(BIO *bio) {
|
||||
if (!bio) {
|
||||
return NULL;
|
||||
}
|
||||
return bio->next_bio;
|
||||
}
|
||||
|
||||
BIO *BIO_find_type(BIO *bio, int type) {
|
||||
int method_type, mask;
|
||||
|
||||
if (!bio) {
|
||||
return NULL;
|
||||
}
|
||||
mask = type & 0xff;
|
||||
|
||||
do {
|
||||
if (bio->method != NULL) {
|
||||
method_type = bio->method->type;
|
||||
|
||||
if (!mask) {
|
||||
if (method_type & type) {
|
||||
return bio;
|
||||
}
|
||||
} else if (method_type == type) {
|
||||
return bio;
|
||||
}
|
||||
}
|
||||
bio = bio->next_bio;
|
||||
} while (bio != NULL);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int BIO_indent(BIO *bio, unsigned indent, unsigned max_indent) {
|
||||
if (indent > max_indent) {
|
||||
indent = max_indent;
|
||||
}
|
||||
|
||||
while (indent--) {
|
||||
if (BIO_puts(bio, " ") != 1) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int print_bio(const char *str, size_t len, void *bio) {
|
||||
return BIO_write((BIO *)bio, str, len);
|
||||
}
|
||||
|
||||
void ERR_print_errors(BIO *bio) {
|
||||
ERR_print_errors_cb(print_bio, bio);
|
||||
}
|
||||
|
||||
// bio_read_all reads everything from |bio| and prepends |prefix| to it. On
|
||||
// success, |*out| is set to an allocated buffer (which should be freed with
|
||||
// |OPENSSL_free|), |*out_len| is set to its length and one is returned. The
|
||||
// buffer will contain |prefix| followed by the contents of |bio|. On failure,
|
||||
// zero is returned.
|
||||
//
|
||||
// The function will fail if the size of the output would equal or exceed
|
||||
// |max_len|.
|
||||
static int bio_read_all(BIO *bio, uint8_t **out, size_t *out_len,
|
||||
const uint8_t *prefix, size_t prefix_len,
|
||||
size_t max_len) {
|
||||
static const size_t kChunkSize = 4096;
|
||||
|
||||
size_t len = prefix_len + kChunkSize;
|
||||
if (len > max_len) {
|
||||
len = max_len;
|
||||
}
|
||||
if (len < prefix_len) {
|
||||
return 0;
|
||||
}
|
||||
*out = OPENSSL_malloc(len);
|
||||
if (*out == NULL) {
|
||||
return 0;
|
||||
}
|
||||
OPENSSL_memcpy(*out, prefix, prefix_len);
|
||||
size_t done = prefix_len;
|
||||
|
||||
for (;;) {
|
||||
if (done == len) {
|
||||
OPENSSL_free(*out);
|
||||
return 0;
|
||||
}
|
||||
const size_t todo = len - done;
|
||||
assert(todo < INT_MAX);
|
||||
const int n = BIO_read(bio, *out + done, todo);
|
||||
if (n == 0) {
|
||||
*out_len = done;
|
||||
return 1;
|
||||
} else if (n == -1) {
|
||||
OPENSSL_free(*out);
|
||||
return 0;
|
||||
}
|
||||
|
||||
done += n;
|
||||
if (len < max_len && len - done < kChunkSize / 2) {
|
||||
len += kChunkSize;
|
||||
if (len < kChunkSize || len > max_len) {
|
||||
len = max_len;
|
||||
}
|
||||
uint8_t *new_buf = OPENSSL_realloc(*out, len);
|
||||
if (new_buf == NULL) {
|
||||
OPENSSL_free(*out);
|
||||
return 0;
|
||||
}
|
||||
*out = new_buf;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// bio_read_full reads |len| bytes |bio| and writes them into |out|. It
|
||||
// tolerates partial reads from |bio| and returns one on success or zero if a
|
||||
// read fails before |len| bytes are read. On failure, it additionally sets
|
||||
// |*out_eof_on_first_read| to whether the error was due to |bio| returning zero
|
||||
// on the first read. |out_eof_on_first_read| may be NULL to discard the value.
|
||||
static int bio_read_full(BIO *bio, uint8_t *out, int *out_eof_on_first_read,
|
||||
size_t len) {
|
||||
int first_read = 1;
|
||||
while (len > 0) {
|
||||
int todo = len <= INT_MAX ? (int)len : INT_MAX;
|
||||
int ret = BIO_read(bio, out, todo);
|
||||
if (ret <= 0) {
|
||||
if (out_eof_on_first_read != NULL) {
|
||||
*out_eof_on_first_read = first_read && ret == 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
out += ret;
|
||||
len -= (size_t)ret;
|
||||
first_read = 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
// For compatibility with existing |d2i_*_bio| callers, |BIO_read_asn1| uses
|
||||
// |ERR_LIB_ASN1| errors.
|
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, ASN1_R_DECODE_ERROR)
|
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, ASN1_R_HEADER_TOO_LONG)
|
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, ASN1_R_NOT_ENOUGH_DATA)
|
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, ASN1_R_TOO_LONG)
|
||||
|
||||
int BIO_read_asn1(BIO *bio, uint8_t **out, size_t *out_len, size_t max_len) {
|
||||
uint8_t header[6];
|
||||
|
||||
static const size_t kInitialHeaderLen = 2;
|
||||
int eof_on_first_read;
|
||||
if (!bio_read_full(bio, header, &eof_on_first_read, kInitialHeaderLen)) {
|
||||
if (eof_on_first_read) {
|
||||
// Historically, OpenSSL returned |ASN1_R_HEADER_TOO_LONG| when
|
||||
// |d2i_*_bio| could not read anything. CPython conditions on this to
|
||||
// determine if |bio| was empty.
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_HEADER_TOO_LONG);
|
||||
} else {
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_NOT_ENOUGH_DATA);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
const uint8_t tag = header[0];
|
||||
const uint8_t length_byte = header[1];
|
||||
|
||||
if ((tag & 0x1f) == 0x1f) {
|
||||
// Long form tags are not supported.
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_DECODE_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t len, header_len;
|
||||
if ((length_byte & 0x80) == 0) {
|
||||
// Short form length.
|
||||
len = length_byte;
|
||||
header_len = kInitialHeaderLen;
|
||||
} else {
|
||||
const size_t num_bytes = length_byte & 0x7f;
|
||||
|
||||
if ((tag & 0x20 /* constructed */) != 0 && num_bytes == 0) {
|
||||
// indefinite length.
|
||||
if (!bio_read_all(bio, out, out_len, header, kInitialHeaderLen,
|
||||
max_len)) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_NOT_ENOUGH_DATA);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (num_bytes == 0 || num_bytes > 4) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_DECODE_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!bio_read_full(bio, header + kInitialHeaderLen, NULL, num_bytes)) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_NOT_ENOUGH_DATA);
|
||||
return 0;
|
||||
}
|
||||
header_len = kInitialHeaderLen + num_bytes;
|
||||
|
||||
uint32_t len32 = 0;
|
||||
for (unsigned i = 0; i < num_bytes; i++) {
|
||||
len32 <<= 8;
|
||||
len32 |= header[kInitialHeaderLen + i];
|
||||
}
|
||||
|
||||
if (len32 < 128) {
|
||||
// Length should have used short-form encoding.
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_DECODE_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((len32 >> ((num_bytes-1)*8)) == 0) {
|
||||
// Length should have been at least one byte shorter.
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_DECODE_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
len = len32;
|
||||
}
|
||||
|
||||
if (len + header_len < len ||
|
||||
len + header_len > max_len ||
|
||||
len > INT_MAX) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_TOO_LONG);
|
||||
return 0;
|
||||
}
|
||||
len += header_len;
|
||||
*out_len = len;
|
||||
|
||||
*out = OPENSSL_malloc(len);
|
||||
if (*out == NULL) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
OPENSSL_memcpy(*out, header, header_len);
|
||||
if (!bio_read_full(bio, (*out) + header_len, NULL, len - header_len)) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_NOT_ENOUGH_DATA);
|
||||
OPENSSL_free(*out);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void BIO_set_retry_special(BIO *bio) {
|
||||
bio->flags |= BIO_FLAGS_READ | BIO_FLAGS_IO_SPECIAL;
|
||||
}
|
||||
|
||||
int BIO_set_write_buffer_size(BIO *bio, int buffer_size) { return 0; }
|
||||
|
||||
static struct CRYPTO_STATIC_MUTEX g_index_lock = CRYPTO_STATIC_MUTEX_INIT;
|
||||
static int g_index = BIO_TYPE_START;
|
||||
|
||||
int BIO_get_new_index(void) {
|
||||
CRYPTO_STATIC_MUTEX_lock_write(&g_index_lock);
|
||||
// If |g_index| exceeds 255, it will collide with the flags bits.
|
||||
int ret = g_index > 255 ? -1 : g_index++;
|
||||
CRYPTO_STATIC_MUTEX_unlock_write(&g_index_lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
BIO_METHOD *BIO_meth_new(int type, const char *name) {
|
||||
BIO_METHOD *method = OPENSSL_malloc(sizeof(BIO_METHOD));
|
||||
if (method == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
OPENSSL_memset(method, 0, sizeof(BIO_METHOD));
|
||||
method->type = type;
|
||||
method->name = name;
|
||||
return method;
|
||||
}
|
||||
|
||||
void BIO_meth_free(BIO_METHOD *method) {
|
||||
OPENSSL_free(method);
|
||||
}
|
||||
|
||||
int BIO_meth_set_create(BIO_METHOD *method,
|
||||
int (*create)(BIO *)) {
|
||||
method->create = create;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int BIO_meth_set_destroy(BIO_METHOD *method,
|
||||
int (*destroy)(BIO *)) {
|
||||
method->destroy = destroy;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int BIO_meth_set_write(BIO_METHOD *method,
|
||||
int (*write)(BIO *, const char *, int)) {
|
||||
method->bwrite = write;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int BIO_meth_set_read(BIO_METHOD *method,
|
||||
int (*read)(BIO *, char *, int)) {
|
||||
method->bread = read;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int BIO_meth_set_gets(BIO_METHOD *method,
|
||||
int (*gets)(BIO *, char *, int)) {
|
||||
method->bgets = gets;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int BIO_meth_set_ctrl(BIO_METHOD *method,
|
||||
long (*ctrl)(BIO *, int, long, void *)) {
|
||||
method->ctrl = ctrl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void BIO_set_data(BIO *bio, void *ptr) { bio->ptr = ptr; }
|
||||
|
||||
void *BIO_get_data(BIO *bio) { return bio->ptr; }
|
||||
|
||||
void BIO_set_init(BIO *bio, int init) { bio->init = init; }
|
||||
|
||||
int BIO_get_init(BIO *bio) { return bio->init; }
|
||||
|
||||
void BIO_set_shutdown(BIO *bio, int shutdown) { bio->shutdown = shutdown; }
|
||||
|
||||
int BIO_get_shutdown(BIO *bio) { return bio->shutdown; }
|
||||
|
||||
int BIO_meth_set_puts(BIO_METHOD *method, int (*puts)(BIO *, const char *)) {
|
||||
// Ignore the parameter. We implement |BIO_puts| using |BIO_write|.
|
||||
return 1;
|
||||
}
|
||||
+700
@@ -0,0 +1,700 @@
|
||||
/* Copyright (C) 1995-1998 Eric Young ([email protected])
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young ([email protected]).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson ([email protected]).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young ([email protected])"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson ([email protected])"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.] */
|
||||
|
||||
#include <openssl/bio.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <openssl/asn1.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/mem.h>
|
||||
#include <openssl/thread.h>
|
||||
|
||||
#include "../internal.h"
|
||||
|
||||
|
||||
BIO *BIO_new(const BIO_METHOD *method) {
|
||||
BIO *ret = OPENSSL_malloc(sizeof(BIO));
|
||||
if (ret == NULL) {
|
||||
OPENSSL_PUT_ERROR(BIO, ERR_R_MALLOC_FAILURE);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
OPENSSL_memset(ret, 0, sizeof(BIO));
|
||||
ret->method = method;
|
||||
ret->shutdown = 1;
|
||||
ret->references = 1;
|
||||
|
||||
if (method->create != NULL && !method->create(ret)) {
|
||||
OPENSSL_free(ret);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int BIO_free(BIO *bio) {
|
||||
BIO *next_bio;
|
||||
|
||||
for (; bio != NULL; bio = next_bio) {
|
||||
if (!CRYPTO_refcount_dec_and_test_zero(&bio->references)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
next_bio = BIO_pop(bio);
|
||||
|
||||
if (bio->method != NULL && bio->method->destroy != NULL) {
|
||||
bio->method->destroy(bio);
|
||||
}
|
||||
|
||||
OPENSSL_free(bio);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int BIO_up_ref(BIO *bio) {
|
||||
CRYPTO_refcount_inc(&bio->references);
|
||||
return 1;
|
||||
}
|
||||
|
||||
void BIO_vfree(BIO *bio) {
|
||||
BIO_free(bio);
|
||||
}
|
||||
|
||||
void BIO_free_all(BIO *bio) {
|
||||
BIO_free(bio);
|
||||
}
|
||||
|
||||
int BIO_read(BIO *bio, void *buf, int len) {
|
||||
if (bio == NULL || bio->method == NULL || bio->method->bread == NULL) {
|
||||
OPENSSL_PUT_ERROR(BIO, BIO_R_UNSUPPORTED_METHOD);
|
||||
return -2;
|
||||
}
|
||||
if (!bio->init) {
|
||||
OPENSSL_PUT_ERROR(BIO, BIO_R_UNINITIALIZED);
|
||||
return -2;
|
||||
}
|
||||
if (len <= 0) {
|
||||
return 0;
|
||||
}
|
||||
int ret = bio->method->bread(bio, buf, len);
|
||||
if (ret > 0) {
|
||||
bio->num_read += ret;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int BIO_gets(BIO *bio, char *buf, int len) {
|
||||
if (bio == NULL || bio->method == NULL || bio->method->bgets == NULL) {
|
||||
OPENSSL_PUT_ERROR(BIO, BIO_R_UNSUPPORTED_METHOD);
|
||||
return -2;
|
||||
}
|
||||
if (!bio->init) {
|
||||
OPENSSL_PUT_ERROR(BIO, BIO_R_UNINITIALIZED);
|
||||
return -2;
|
||||
}
|
||||
if (len <= 0) {
|
||||
return 0;
|
||||
}
|
||||
int ret = bio->method->bgets(bio, buf, len);
|
||||
if (ret > 0) {
|
||||
bio->num_read += ret;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int BIO_write(BIO *bio, const void *in, int inl) {
|
||||
if (bio == NULL || bio->method == NULL || bio->method->bwrite == NULL) {
|
||||
OPENSSL_PUT_ERROR(BIO, BIO_R_UNSUPPORTED_METHOD);
|
||||
return -2;
|
||||
}
|
||||
if (!bio->init) {
|
||||
OPENSSL_PUT_ERROR(BIO, BIO_R_UNINITIALIZED);
|
||||
return -2;
|
||||
}
|
||||
if (inl <= 0) {
|
||||
return 0;
|
||||
}
|
||||
int ret = bio->method->bwrite(bio, in, inl);
|
||||
if (ret > 0) {
|
||||
bio->num_write += ret;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int BIO_write_all(BIO *bio, const void *data, size_t len) {
|
||||
const uint8_t *data_u8 = data;
|
||||
while (len > 0) {
|
||||
int ret = BIO_write(bio, data_u8, len > INT_MAX ? INT_MAX : (int)len);
|
||||
if (ret <= 0) {
|
||||
return 0;
|
||||
}
|
||||
data_u8 += ret;
|
||||
len -= ret;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int BIO_puts(BIO *bio, const char *in) {
|
||||
return BIO_write(bio, in, strlen(in));
|
||||
}
|
||||
|
||||
int BIO_flush(BIO *bio) {
|
||||
return BIO_ctrl(bio, BIO_CTRL_FLUSH, 0, NULL);
|
||||
}
|
||||
|
||||
long BIO_ctrl(BIO *bio, int cmd, long larg, void *parg) {
|
||||
if (bio == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (bio->method == NULL || bio->method->ctrl == NULL) {
|
||||
OPENSSL_PUT_ERROR(BIO, BIO_R_UNSUPPORTED_METHOD);
|
||||
return -2;
|
||||
}
|
||||
|
||||
return bio->method->ctrl(bio, cmd, larg, parg);
|
||||
}
|
||||
|
||||
char *BIO_ptr_ctrl(BIO *b, int cmd, long larg) {
|
||||
char *p = NULL;
|
||||
|
||||
if (BIO_ctrl(b, cmd, larg, (void *)&p) <= 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
long BIO_int_ctrl(BIO *b, int cmd, long larg, int iarg) {
|
||||
int i = iarg;
|
||||
|
||||
return BIO_ctrl(b, cmd, larg, (void *)&i);
|
||||
}
|
||||
|
||||
int BIO_reset(BIO *bio) {
|
||||
return BIO_ctrl(bio, BIO_CTRL_RESET, 0, NULL);
|
||||
}
|
||||
|
||||
int BIO_eof(BIO *bio) {
|
||||
return BIO_ctrl(bio, BIO_CTRL_EOF, 0, NULL);
|
||||
}
|
||||
|
||||
void BIO_set_flags(BIO *bio, int flags) {
|
||||
bio->flags |= flags;
|
||||
}
|
||||
|
||||
int BIO_test_flags(const BIO *bio, int flags) {
|
||||
return bio->flags & flags;
|
||||
}
|
||||
|
||||
int BIO_should_read(const BIO *bio) {
|
||||
return BIO_test_flags(bio, BIO_FLAGS_READ);
|
||||
}
|
||||
|
||||
int BIO_should_write(const BIO *bio) {
|
||||
return BIO_test_flags(bio, BIO_FLAGS_WRITE);
|
||||
}
|
||||
|
||||
int BIO_should_retry(const BIO *bio) {
|
||||
return BIO_test_flags(bio, BIO_FLAGS_SHOULD_RETRY);
|
||||
}
|
||||
|
||||
int BIO_should_io_special(const BIO *bio) {
|
||||
return BIO_test_flags(bio, BIO_FLAGS_IO_SPECIAL);
|
||||
}
|
||||
|
||||
int BIO_get_retry_reason(const BIO *bio) { return bio->retry_reason; }
|
||||
|
||||
void BIO_clear_flags(BIO *bio, int flags) {
|
||||
bio->flags &= ~flags;
|
||||
}
|
||||
|
||||
void BIO_set_retry_read(BIO *bio) {
|
||||
bio->flags |= BIO_FLAGS_READ | BIO_FLAGS_SHOULD_RETRY;
|
||||
}
|
||||
|
||||
void BIO_set_retry_write(BIO *bio) {
|
||||
bio->flags |= BIO_FLAGS_WRITE | BIO_FLAGS_SHOULD_RETRY;
|
||||
}
|
||||
|
||||
static const int kRetryFlags = BIO_FLAGS_RWS | BIO_FLAGS_SHOULD_RETRY;
|
||||
|
||||
int BIO_get_retry_flags(BIO *bio) {
|
||||
return bio->flags & kRetryFlags;
|
||||
}
|
||||
|
||||
void BIO_clear_retry_flags(BIO *bio) {
|
||||
bio->flags &= ~kRetryFlags;
|
||||
bio->retry_reason = 0;
|
||||
}
|
||||
|
||||
int BIO_method_type(const BIO *bio) { return bio->method->type; }
|
||||
|
||||
void BIO_copy_next_retry(BIO *bio) {
|
||||
BIO_clear_retry_flags(bio);
|
||||
BIO_set_flags(bio, BIO_get_retry_flags(bio->next_bio));
|
||||
bio->retry_reason = bio->next_bio->retry_reason;
|
||||
}
|
||||
|
||||
long BIO_callback_ctrl(BIO *bio, int cmd, bio_info_cb fp) {
|
||||
if (bio == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (bio->method == NULL || bio->method->callback_ctrl == NULL) {
|
||||
OPENSSL_PUT_ERROR(BIO, BIO_R_UNSUPPORTED_METHOD);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return bio->method->callback_ctrl(bio, cmd, fp);
|
||||
}
|
||||
|
||||
size_t BIO_pending(const BIO *bio) {
|
||||
const long r = BIO_ctrl((BIO *) bio, BIO_CTRL_PENDING, 0, NULL);
|
||||
assert(r >= 0);
|
||||
|
||||
if (r < 0) {
|
||||
return 0;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
size_t BIO_ctrl_pending(const BIO *bio) {
|
||||
return BIO_pending(bio);
|
||||
}
|
||||
|
||||
size_t BIO_wpending(const BIO *bio) {
|
||||
const long r = BIO_ctrl((BIO *) bio, BIO_CTRL_WPENDING, 0, NULL);
|
||||
assert(r >= 0);
|
||||
|
||||
if (r < 0) {
|
||||
return 0;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
int BIO_set_close(BIO *bio, int close_flag) {
|
||||
return BIO_ctrl(bio, BIO_CTRL_SET_CLOSE, close_flag, NULL);
|
||||
}
|
||||
|
||||
OPENSSL_EXPORT size_t BIO_number_read(const BIO *bio) {
|
||||
return bio->num_read;
|
||||
}
|
||||
|
||||
OPENSSL_EXPORT size_t BIO_number_written(const BIO *bio) {
|
||||
return bio->num_write;
|
||||
}
|
||||
|
||||
BIO *BIO_push(BIO *bio, BIO *appended_bio) {
|
||||
BIO *last_bio;
|
||||
|
||||
if (bio == NULL) {
|
||||
return bio;
|
||||
}
|
||||
|
||||
last_bio = bio;
|
||||
while (last_bio->next_bio != NULL) {
|
||||
last_bio = last_bio->next_bio;
|
||||
}
|
||||
|
||||
last_bio->next_bio = appended_bio;
|
||||
return bio;
|
||||
}
|
||||
|
||||
BIO *BIO_pop(BIO *bio) {
|
||||
BIO *ret;
|
||||
|
||||
if (bio == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
ret = bio->next_bio;
|
||||
bio->next_bio = NULL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
BIO *BIO_next(BIO *bio) {
|
||||
if (!bio) {
|
||||
return NULL;
|
||||
}
|
||||
return bio->next_bio;
|
||||
}
|
||||
|
||||
BIO *BIO_find_type(BIO *bio, int type) {
|
||||
int method_type, mask;
|
||||
|
||||
if (!bio) {
|
||||
return NULL;
|
||||
}
|
||||
mask = type & 0xff;
|
||||
|
||||
do {
|
||||
if (bio->method != NULL) {
|
||||
method_type = bio->method->type;
|
||||
|
||||
if (!mask) {
|
||||
if (method_type & type) {
|
||||
return bio;
|
||||
}
|
||||
} else if (method_type == type) {
|
||||
return bio;
|
||||
}
|
||||
}
|
||||
bio = bio->next_bio;
|
||||
} while (bio != NULL);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int BIO_indent(BIO *bio, unsigned indent, unsigned max_indent) {
|
||||
if (indent > max_indent) {
|
||||
indent = max_indent;
|
||||
}
|
||||
|
||||
while (indent--) {
|
||||
if (BIO_puts(bio, " ") != 1) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int print_bio(const char *str, size_t len, void *bio) {
|
||||
return BIO_write((BIO *)bio, str, len);
|
||||
}
|
||||
|
||||
void ERR_print_errors(BIO *bio) {
|
||||
ERR_print_errors_cb(print_bio, bio);
|
||||
}
|
||||
|
||||
// bio_read_all reads everything from |bio| and prepends |prefix| to it. On
|
||||
// success, |*out| is set to an allocated buffer (which should be freed with
|
||||
// |OPENSSL_free|), |*out_len| is set to its length and one is returned. The
|
||||
// buffer will contain |prefix| followed by the contents of |bio|. On failure,
|
||||
// zero is returned.
|
||||
//
|
||||
// The function will fail if the size of the output would equal or exceed
|
||||
// |max_len|.
|
||||
static int bio_read_all(BIO *bio, uint8_t **out, size_t *out_len,
|
||||
const uint8_t *prefix, size_t prefix_len,
|
||||
size_t max_len) {
|
||||
static const size_t kChunkSize = 4096;
|
||||
|
||||
size_t len = prefix_len + kChunkSize;
|
||||
if (len > max_len) {
|
||||
len = max_len;
|
||||
}
|
||||
if (len < prefix_len) {
|
||||
return 0;
|
||||
}
|
||||
*out = OPENSSL_malloc(len);
|
||||
if (*out == NULL) {
|
||||
return 0;
|
||||
}
|
||||
OPENSSL_memcpy(*out, prefix, prefix_len);
|
||||
size_t done = prefix_len;
|
||||
|
||||
for (;;) {
|
||||
if (done == len) {
|
||||
OPENSSL_free(*out);
|
||||
return 0;
|
||||
}
|
||||
const size_t todo = len - done;
|
||||
assert(todo < INT_MAX);
|
||||
const int n = BIO_read(bio, *out + done, todo);
|
||||
if (n == 0) {
|
||||
*out_len = done;
|
||||
return 1;
|
||||
} else if (n == -1) {
|
||||
OPENSSL_free(*out);
|
||||
return 0;
|
||||
}
|
||||
|
||||
done += n;
|
||||
if (len < max_len && len - done < kChunkSize / 2) {
|
||||
len += kChunkSize;
|
||||
if (len < kChunkSize || len > max_len) {
|
||||
len = max_len;
|
||||
}
|
||||
uint8_t *new_buf = OPENSSL_realloc(*out, len);
|
||||
if (new_buf == NULL) {
|
||||
OPENSSL_free(*out);
|
||||
return 0;
|
||||
}
|
||||
*out = new_buf;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// bio_read_full reads |len| bytes |bio| and writes them into |out|. It
|
||||
// tolerates partial reads from |bio| and returns one on success or zero if a
|
||||
// read fails before |len| bytes are read. On failure, it additionally sets
|
||||
// |*out_eof_on_first_read| to whether the error was due to |bio| returning zero
|
||||
// on the first read. |out_eof_on_first_read| may be NULL to discard the value.
|
||||
static int bio_read_full(BIO *bio, uint8_t *out, int *out_eof_on_first_read,
|
||||
size_t len) {
|
||||
int first_read = 1;
|
||||
while (len > 0) {
|
||||
int todo = len <= INT_MAX ? (int)len : INT_MAX;
|
||||
int ret = BIO_read(bio, out, todo);
|
||||
if (ret <= 0) {
|
||||
if (out_eof_on_first_read != NULL) {
|
||||
*out_eof_on_first_read = first_read && ret == 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
out += ret;
|
||||
len -= (size_t)ret;
|
||||
first_read = 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
// For compatibility with existing |d2i_*_bio| callers, |BIO_read_asn1| uses
|
||||
// |ERR_LIB_ASN1| errors.
|
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, ASN1_R_DECODE_ERROR)
|
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, ASN1_R_HEADER_TOO_LONG)
|
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, ASN1_R_NOT_ENOUGH_DATA)
|
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, ASN1_R_TOO_LONG)
|
||||
|
||||
int BIO_read_asn1(BIO *bio, uint8_t **out, size_t *out_len, size_t max_len) {
|
||||
uint8_t header[6];
|
||||
|
||||
static const size_t kInitialHeaderLen = 2;
|
||||
int eof_on_first_read;
|
||||
if (!bio_read_full(bio, header, &eof_on_first_read, kInitialHeaderLen)) {
|
||||
if (eof_on_first_read) {
|
||||
// Historically, OpenSSL returned |ASN1_R_HEADER_TOO_LONG| when
|
||||
// |d2i_*_bio| could not read anything. CPython conditions on this to
|
||||
// determine if |bio| was empty.
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_HEADER_TOO_LONG);
|
||||
} else {
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_NOT_ENOUGH_DATA);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
const uint8_t tag = header[0];
|
||||
const uint8_t length_byte = header[1];
|
||||
|
||||
if ((tag & 0x1f) == 0x1f) {
|
||||
// Long form tags are not supported.
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_DECODE_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t len, header_len;
|
||||
if ((length_byte & 0x80) == 0) {
|
||||
// Short form length.
|
||||
len = length_byte;
|
||||
header_len = kInitialHeaderLen;
|
||||
} else {
|
||||
const size_t num_bytes = length_byte & 0x7f;
|
||||
|
||||
if ((tag & 0x20 /* constructed */) != 0 && num_bytes == 0) {
|
||||
// indefinite length.
|
||||
if (!bio_read_all(bio, out, out_len, header, kInitialHeaderLen,
|
||||
max_len)) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_NOT_ENOUGH_DATA);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (num_bytes == 0 || num_bytes > 4) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_DECODE_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!bio_read_full(bio, header + kInitialHeaderLen, NULL, num_bytes)) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_NOT_ENOUGH_DATA);
|
||||
return 0;
|
||||
}
|
||||
header_len = kInitialHeaderLen + num_bytes;
|
||||
|
||||
uint32_t len32 = 0;
|
||||
for (unsigned i = 0; i < num_bytes; i++) {
|
||||
len32 <<= 8;
|
||||
len32 |= header[kInitialHeaderLen + i];
|
||||
}
|
||||
|
||||
if (len32 < 128) {
|
||||
// Length should have used short-form encoding.
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_DECODE_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((len32 >> ((num_bytes-1)*8)) == 0) {
|
||||
// Length should have been at least one byte shorter.
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_DECODE_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
len = len32;
|
||||
}
|
||||
|
||||
if (len + header_len < len ||
|
||||
len + header_len > max_len ||
|
||||
len > INT_MAX) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_TOO_LONG);
|
||||
return 0;
|
||||
}
|
||||
len += header_len;
|
||||
*out_len = len;
|
||||
|
||||
*out = OPENSSL_malloc(len);
|
||||
if (*out == NULL) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
OPENSSL_memcpy(*out, header, header_len);
|
||||
if (!bio_read_full(bio, (*out) + header_len, NULL, len - header_len)) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_NOT_ENOUGH_DATA);
|
||||
OPENSSL_free(*out);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void BIO_set_retry_special(BIO *bio) {
|
||||
bio->flags |= BIO_FLAGS_READ | BIO_FLAGS_IO_SPECIAL;
|
||||
}
|
||||
|
||||
int BIO_set_write_buffer_size(BIO *bio, int buffer_size) { return 0; }
|
||||
|
||||
static struct CRYPTO_STATIC_MUTEX g_index_lock = CRYPTO_STATIC_MUTEX_INIT;
|
||||
static int g_index = BIO_TYPE_START;
|
||||
|
||||
int BIO_get_new_index(void) {
|
||||
CRYPTO_STATIC_MUTEX_lock_write(&g_index_lock);
|
||||
// If |g_index| exceeds 255, it will collide with the flags bits.
|
||||
int ret = g_index > 255 ? -1 : g_index++;
|
||||
CRYPTO_STATIC_MUTEX_unlock_write(&g_index_lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
BIO_METHOD *BIO_meth_new(int type, const char *name) {
|
||||
BIO_METHOD *method = OPENSSL_malloc(sizeof(BIO_METHOD));
|
||||
if (method == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
OPENSSL_memset(method, 0, sizeof(BIO_METHOD));
|
||||
method->type = type;
|
||||
method->name = name;
|
||||
return method;
|
||||
}
|
||||
|
||||
void BIO_meth_free(BIO_METHOD *method) {
|
||||
OPENSSL_free(method);
|
||||
}
|
||||
|
||||
int BIO_meth_set_create(BIO_METHOD *method,
|
||||
int (*create)(BIO *)) {
|
||||
method->create = create;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int BIO_meth_set_destroy(BIO_METHOD *method,
|
||||
int (*destroy)(BIO *)) {
|
||||
method->destroy = destroy;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int BIO_meth_set_write(BIO_METHOD *method,
|
||||
int (*write)(BIO *, const char *, int)) {
|
||||
method->bwrite = write;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int BIO_meth_set_read(BIO_METHOD *method,
|
||||
int (*read)(BIO *, char *, int)) {
|
||||
method->bread = read;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int BIO_meth_set_gets(BIO_METHOD *method,
|
||||
int (*gets)(BIO *, char *, int)) {
|
||||
method->bgets = gets;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int BIO_meth_set_ctrl(BIO_METHOD *method,
|
||||
long (*ctrl)(BIO *, int, long, void *)) {
|
||||
method->ctrl = ctrl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void BIO_set_data(BIO *bio, void *ptr) { bio->ptr = ptr; }
|
||||
|
||||
void *BIO_get_data(BIO *bio) { return bio->ptr; }
|
||||
|
||||
void BIO_set_init(BIO *bio, int init) { bio->init = init; }
|
||||
|
||||
int BIO_get_init(BIO *bio) { return bio->init; }
|
||||
|
||||
void BIO_set_shutdown(BIO *bio, int shutdown) { bio->shutdown = shutdown; }
|
||||
|
||||
int BIO_get_shutdown(BIO *bio) { return bio->shutdown; }
|
||||
|
||||
int BIO_meth_set_puts(BIO_METHOD *method, int (*puts)(BIO *, const char *)) {
|
||||
// Ignore the parameter. We implement |BIO_puts| using |BIO_write|.
|
||||
return 1;
|
||||
}
|
||||
+330
@@ -0,0 +1,330 @@
|
||||
/* Copyright (C) 1995-1998 Eric Young ([email protected])
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young ([email protected]).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson ([email protected]).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young ([email protected])"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson ([email protected])"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.] */
|
||||
|
||||
#include <openssl_grpc/bio.h>
|
||||
|
||||
#include <limits.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <openssl_grpc/buf.h>
|
||||
#include <openssl_grpc/err.h>
|
||||
#include <openssl_grpc/mem.h>
|
||||
|
||||
#include "../internal.h"
|
||||
|
||||
|
||||
BIO *BIO_new_mem_buf(const void *buf, int len) {
|
||||
BIO *ret;
|
||||
BUF_MEM *b;
|
||||
const size_t size = len < 0 ? strlen((char *)buf) : (size_t)len;
|
||||
|
||||
if (!buf && len != 0) {
|
||||
OPENSSL_PUT_ERROR(BIO, BIO_R_NULL_PARAMETER);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ret = BIO_new(BIO_s_mem());
|
||||
if (ret == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
b = (BUF_MEM *)ret->ptr;
|
||||
// BIO_FLAGS_MEM_RDONLY ensures |b->data| is not written to.
|
||||
b->data = (void *)buf;
|
||||
b->length = size;
|
||||
b->max = size;
|
||||
|
||||
ret->flags |= BIO_FLAGS_MEM_RDONLY;
|
||||
|
||||
// |num| is used to store the value that this BIO will return when it runs
|
||||
// out of data. If it's negative then the retry flags will also be set. Since
|
||||
// this is static data, retrying wont help
|
||||
ret->num = 0;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int mem_new(BIO *bio) {
|
||||
BUF_MEM *b;
|
||||
|
||||
b = BUF_MEM_new();
|
||||
if (b == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// |shutdown| is used to store the close flag: whether the BIO has ownership
|
||||
// of the BUF_MEM.
|
||||
bio->shutdown = 1;
|
||||
bio->init = 1;
|
||||
bio->num = -1;
|
||||
bio->ptr = (char *)b;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int mem_free(BIO *bio) {
|
||||
BUF_MEM *b;
|
||||
|
||||
if (bio == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!bio->shutdown || !bio->init || bio->ptr == NULL) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
b = (BUF_MEM *)bio->ptr;
|
||||
if (bio->flags & BIO_FLAGS_MEM_RDONLY) {
|
||||
b->data = NULL;
|
||||
}
|
||||
BUF_MEM_free(b);
|
||||
bio->ptr = NULL;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int mem_read(BIO *bio, char *out, int outl) {
|
||||
int ret;
|
||||
BUF_MEM *b = (BUF_MEM*) bio->ptr;
|
||||
|
||||
BIO_clear_retry_flags(bio);
|
||||
ret = outl;
|
||||
if (b->length < INT_MAX && ret > (int)b->length) {
|
||||
ret = b->length;
|
||||
}
|
||||
|
||||
if (ret > 0) {
|
||||
OPENSSL_memcpy(out, b->data, ret);
|
||||
b->length -= ret;
|
||||
if (bio->flags & BIO_FLAGS_MEM_RDONLY) {
|
||||
b->data += ret;
|
||||
} else {
|
||||
OPENSSL_memmove(b->data, &b->data[ret], b->length);
|
||||
}
|
||||
} else if (b->length == 0) {
|
||||
ret = bio->num;
|
||||
if (ret != 0) {
|
||||
BIO_set_retry_read(bio);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int mem_write(BIO *bio, const char *in, int inl) {
|
||||
int ret = -1;
|
||||
int blen;
|
||||
BUF_MEM *b;
|
||||
|
||||
b = (BUF_MEM *)bio->ptr;
|
||||
|
||||
if (bio->flags & BIO_FLAGS_MEM_RDONLY) {
|
||||
OPENSSL_PUT_ERROR(BIO, BIO_R_WRITE_TO_READ_ONLY_BIO);
|
||||
goto err;
|
||||
}
|
||||
|
||||
BIO_clear_retry_flags(bio);
|
||||
blen = b->length;
|
||||
if (INT_MAX - blen < inl) {
|
||||
goto err;
|
||||
}
|
||||
if (BUF_MEM_grow_clean(b, blen + inl) != ((size_t) blen) + inl) {
|
||||
goto err;
|
||||
}
|
||||
OPENSSL_memcpy(&b->data[blen], in, inl);
|
||||
ret = inl;
|
||||
|
||||
err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int mem_gets(BIO *bio, char *buf, int size) {
|
||||
int i, j;
|
||||
char *p;
|
||||
BUF_MEM *b = (BUF_MEM *)bio->ptr;
|
||||
|
||||
BIO_clear_retry_flags(bio);
|
||||
j = b->length;
|
||||
if (size - 1 < j) {
|
||||
j = size - 1;
|
||||
}
|
||||
if (j <= 0) {
|
||||
if (size > 0) {
|
||||
*buf = 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
p = b->data;
|
||||
for (i = 0; i < j; i++) {
|
||||
if (p[i] == '\n') {
|
||||
i++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// i is now the max num of bytes to copy, either j or up to and including the
|
||||
// first newline
|
||||
|
||||
i = mem_read(bio, buf, i);
|
||||
if (i > 0) {
|
||||
buf[i] = '\0';
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
static long mem_ctrl(BIO *bio, int cmd, long num, void *ptr) {
|
||||
long ret = 1;
|
||||
char **pptr;
|
||||
|
||||
BUF_MEM *b = (BUF_MEM *)bio->ptr;
|
||||
|
||||
switch (cmd) {
|
||||
case BIO_CTRL_RESET:
|
||||
if (b->data != NULL) {
|
||||
// For read only case reset to the start again
|
||||
if (bio->flags & BIO_FLAGS_MEM_RDONLY) {
|
||||
b->data -= b->max - b->length;
|
||||
b->length = b->max;
|
||||
} else {
|
||||
OPENSSL_memset(b->data, 0, b->max);
|
||||
b->length = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case BIO_CTRL_EOF:
|
||||
ret = (long)(b->length == 0);
|
||||
break;
|
||||
case BIO_C_SET_BUF_MEM_EOF_RETURN:
|
||||
bio->num = (int)num;
|
||||
break;
|
||||
case BIO_CTRL_INFO:
|
||||
ret = (long)b->length;
|
||||
if (ptr != NULL) {
|
||||
pptr = (char **)ptr;
|
||||
*pptr = (char *)&b->data[0];
|
||||
}
|
||||
break;
|
||||
case BIO_C_SET_BUF_MEM:
|
||||
mem_free(bio);
|
||||
bio->shutdown = (int)num;
|
||||
bio->ptr = ptr;
|
||||
break;
|
||||
case BIO_C_GET_BUF_MEM_PTR:
|
||||
if (ptr != NULL) {
|
||||
pptr = (char **)ptr;
|
||||
*pptr = (char *)b;
|
||||
}
|
||||
break;
|
||||
case BIO_CTRL_GET_CLOSE:
|
||||
ret = (long)bio->shutdown;
|
||||
break;
|
||||
case BIO_CTRL_SET_CLOSE:
|
||||
bio->shutdown = (int)num;
|
||||
break;
|
||||
|
||||
case BIO_CTRL_WPENDING:
|
||||
ret = 0L;
|
||||
break;
|
||||
case BIO_CTRL_PENDING:
|
||||
ret = (long)b->length;
|
||||
break;
|
||||
case BIO_CTRL_FLUSH:
|
||||
ret = 1;
|
||||
break;
|
||||
default:
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const BIO_METHOD mem_method = {
|
||||
BIO_TYPE_MEM, "memory buffer",
|
||||
mem_write, mem_read,
|
||||
NULL /* puts */, mem_gets,
|
||||
mem_ctrl, mem_new,
|
||||
mem_free, NULL /* callback_ctrl */,
|
||||
};
|
||||
|
||||
const BIO_METHOD *BIO_s_mem(void) { return &mem_method; }
|
||||
|
||||
int BIO_mem_contents(const BIO *bio, const uint8_t **out_contents,
|
||||
size_t *out_len) {
|
||||
const BUF_MEM *b;
|
||||
if (bio->method != &mem_method) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
b = (BUF_MEM *)bio->ptr;
|
||||
*out_contents = (uint8_t *)b->data;
|
||||
*out_len = b->length;
|
||||
return 1;
|
||||
}
|
||||
|
||||
long BIO_get_mem_data(BIO *bio, char **contents) {
|
||||
return BIO_ctrl(bio, BIO_CTRL_INFO, 0, (char *) contents);
|
||||
}
|
||||
|
||||
int BIO_get_mem_ptr(BIO *bio, BUF_MEM **out) {
|
||||
return BIO_ctrl(bio, BIO_C_GET_BUF_MEM_PTR, 0, (char *) out);
|
||||
}
|
||||
|
||||
int BIO_set_mem_buf(BIO *bio, BUF_MEM *b, int take_ownership) {
|
||||
return BIO_ctrl(bio, BIO_C_SET_BUF_MEM, take_ownership, (char *) b);
|
||||
}
|
||||
|
||||
int BIO_set_mem_eof_return(BIO *bio, int eof_value) {
|
||||
return BIO_ctrl(bio, BIO_C_SET_BUF_MEM_EOF_RETURN, eof_value, NULL);
|
||||
}
|
||||
+330
@@ -0,0 +1,330 @@
|
||||
/* Copyright (C) 1995-1998 Eric Young ([email protected])
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young ([email protected]).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson ([email protected]).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young ([email protected])"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson ([email protected])"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.] */
|
||||
|
||||
#include <openssl/bio.h>
|
||||
|
||||
#include <limits.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <openssl/buf.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/mem.h>
|
||||
|
||||
#include "../internal.h"
|
||||
|
||||
|
||||
BIO *BIO_new_mem_buf(const void *buf, int len) {
|
||||
BIO *ret;
|
||||
BUF_MEM *b;
|
||||
const size_t size = len < 0 ? strlen((char *)buf) : (size_t)len;
|
||||
|
||||
if (!buf && len != 0) {
|
||||
OPENSSL_PUT_ERROR(BIO, BIO_R_NULL_PARAMETER);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ret = BIO_new(BIO_s_mem());
|
||||
if (ret == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
b = (BUF_MEM *)ret->ptr;
|
||||
// BIO_FLAGS_MEM_RDONLY ensures |b->data| is not written to.
|
||||
b->data = (void *)buf;
|
||||
b->length = size;
|
||||
b->max = size;
|
||||
|
||||
ret->flags |= BIO_FLAGS_MEM_RDONLY;
|
||||
|
||||
// |num| is used to store the value that this BIO will return when it runs
|
||||
// out of data. If it's negative then the retry flags will also be set. Since
|
||||
// this is static data, retrying wont help
|
||||
ret->num = 0;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int mem_new(BIO *bio) {
|
||||
BUF_MEM *b;
|
||||
|
||||
b = BUF_MEM_new();
|
||||
if (b == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// |shutdown| is used to store the close flag: whether the BIO has ownership
|
||||
// of the BUF_MEM.
|
||||
bio->shutdown = 1;
|
||||
bio->init = 1;
|
||||
bio->num = -1;
|
||||
bio->ptr = (char *)b;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int mem_free(BIO *bio) {
|
||||
BUF_MEM *b;
|
||||
|
||||
if (bio == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!bio->shutdown || !bio->init || bio->ptr == NULL) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
b = (BUF_MEM *)bio->ptr;
|
||||
if (bio->flags & BIO_FLAGS_MEM_RDONLY) {
|
||||
b->data = NULL;
|
||||
}
|
||||
BUF_MEM_free(b);
|
||||
bio->ptr = NULL;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int mem_read(BIO *bio, char *out, int outl) {
|
||||
int ret;
|
||||
BUF_MEM *b = (BUF_MEM*) bio->ptr;
|
||||
|
||||
BIO_clear_retry_flags(bio);
|
||||
ret = outl;
|
||||
if (b->length < INT_MAX && ret > (int)b->length) {
|
||||
ret = b->length;
|
||||
}
|
||||
|
||||
if (ret > 0) {
|
||||
OPENSSL_memcpy(out, b->data, ret);
|
||||
b->length -= ret;
|
||||
if (bio->flags & BIO_FLAGS_MEM_RDONLY) {
|
||||
b->data += ret;
|
||||
} else {
|
||||
OPENSSL_memmove(b->data, &b->data[ret], b->length);
|
||||
}
|
||||
} else if (b->length == 0) {
|
||||
ret = bio->num;
|
||||
if (ret != 0) {
|
||||
BIO_set_retry_read(bio);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int mem_write(BIO *bio, const char *in, int inl) {
|
||||
int ret = -1;
|
||||
int blen;
|
||||
BUF_MEM *b;
|
||||
|
||||
b = (BUF_MEM *)bio->ptr;
|
||||
|
||||
if (bio->flags & BIO_FLAGS_MEM_RDONLY) {
|
||||
OPENSSL_PUT_ERROR(BIO, BIO_R_WRITE_TO_READ_ONLY_BIO);
|
||||
goto err;
|
||||
}
|
||||
|
||||
BIO_clear_retry_flags(bio);
|
||||
blen = b->length;
|
||||
if (INT_MAX - blen < inl) {
|
||||
goto err;
|
||||
}
|
||||
if (BUF_MEM_grow_clean(b, blen + inl) != ((size_t) blen) + inl) {
|
||||
goto err;
|
||||
}
|
||||
OPENSSL_memcpy(&b->data[blen], in, inl);
|
||||
ret = inl;
|
||||
|
||||
err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int mem_gets(BIO *bio, char *buf, int size) {
|
||||
int i, j;
|
||||
char *p;
|
||||
BUF_MEM *b = (BUF_MEM *)bio->ptr;
|
||||
|
||||
BIO_clear_retry_flags(bio);
|
||||
j = b->length;
|
||||
if (size - 1 < j) {
|
||||
j = size - 1;
|
||||
}
|
||||
if (j <= 0) {
|
||||
if (size > 0) {
|
||||
*buf = 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
p = b->data;
|
||||
for (i = 0; i < j; i++) {
|
||||
if (p[i] == '\n') {
|
||||
i++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// i is now the max num of bytes to copy, either j or up to and including the
|
||||
// first newline
|
||||
|
||||
i = mem_read(bio, buf, i);
|
||||
if (i > 0) {
|
||||
buf[i] = '\0';
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
static long mem_ctrl(BIO *bio, int cmd, long num, void *ptr) {
|
||||
long ret = 1;
|
||||
char **pptr;
|
||||
|
||||
BUF_MEM *b = (BUF_MEM *)bio->ptr;
|
||||
|
||||
switch (cmd) {
|
||||
case BIO_CTRL_RESET:
|
||||
if (b->data != NULL) {
|
||||
// For read only case reset to the start again
|
||||
if (bio->flags & BIO_FLAGS_MEM_RDONLY) {
|
||||
b->data -= b->max - b->length;
|
||||
b->length = b->max;
|
||||
} else {
|
||||
OPENSSL_memset(b->data, 0, b->max);
|
||||
b->length = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case BIO_CTRL_EOF:
|
||||
ret = (long)(b->length == 0);
|
||||
break;
|
||||
case BIO_C_SET_BUF_MEM_EOF_RETURN:
|
||||
bio->num = (int)num;
|
||||
break;
|
||||
case BIO_CTRL_INFO:
|
||||
ret = (long)b->length;
|
||||
if (ptr != NULL) {
|
||||
pptr = (char **)ptr;
|
||||
*pptr = (char *)&b->data[0];
|
||||
}
|
||||
break;
|
||||
case BIO_C_SET_BUF_MEM:
|
||||
mem_free(bio);
|
||||
bio->shutdown = (int)num;
|
||||
bio->ptr = ptr;
|
||||
break;
|
||||
case BIO_C_GET_BUF_MEM_PTR:
|
||||
if (ptr != NULL) {
|
||||
pptr = (char **)ptr;
|
||||
*pptr = (char *)b;
|
||||
}
|
||||
break;
|
||||
case BIO_CTRL_GET_CLOSE:
|
||||
ret = (long)bio->shutdown;
|
||||
break;
|
||||
case BIO_CTRL_SET_CLOSE:
|
||||
bio->shutdown = (int)num;
|
||||
break;
|
||||
|
||||
case BIO_CTRL_WPENDING:
|
||||
ret = 0L;
|
||||
break;
|
||||
case BIO_CTRL_PENDING:
|
||||
ret = (long)b->length;
|
||||
break;
|
||||
case BIO_CTRL_FLUSH:
|
||||
ret = 1;
|
||||
break;
|
||||
default:
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const BIO_METHOD mem_method = {
|
||||
BIO_TYPE_MEM, "memory buffer",
|
||||
mem_write, mem_read,
|
||||
NULL /* puts */, mem_gets,
|
||||
mem_ctrl, mem_new,
|
||||
mem_free, NULL /* callback_ctrl */,
|
||||
};
|
||||
|
||||
const BIO_METHOD *BIO_s_mem(void) { return &mem_method; }
|
||||
|
||||
int BIO_mem_contents(const BIO *bio, const uint8_t **out_contents,
|
||||
size_t *out_len) {
|
||||
const BUF_MEM *b;
|
||||
if (bio->method != &mem_method) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
b = (BUF_MEM *)bio->ptr;
|
||||
*out_contents = (uint8_t *)b->data;
|
||||
*out_len = b->length;
|
||||
return 1;
|
||||
}
|
||||
|
||||
long BIO_get_mem_data(BIO *bio, char **contents) {
|
||||
return BIO_ctrl(bio, BIO_CTRL_INFO, 0, (char *) contents);
|
||||
}
|
||||
|
||||
int BIO_get_mem_ptr(BIO *bio, BUF_MEM **out) {
|
||||
return BIO_ctrl(bio, BIO_C_GET_BUF_MEM_PTR, 0, (char *) out);
|
||||
}
|
||||
|
||||
int BIO_set_mem_buf(BIO *bio, BUF_MEM *b, int take_ownership) {
|
||||
return BIO_ctrl(bio, BIO_C_SET_BUF_MEM, take_ownership, (char *) b);
|
||||
}
|
||||
|
||||
int BIO_set_mem_eof_return(BIO *bio, int eof_value) {
|
||||
return BIO_ctrl(bio, BIO_C_SET_BUF_MEM_EOF_RETURN, eof_value, NULL);
|
||||
}
|
||||
+545
@@ -0,0 +1,545 @@
|
||||
/* Copyright (C) 1995-1998 Eric Young ([email protected])
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young ([email protected]).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson ([email protected]).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young ([email protected])"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson ([email protected])"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.] */
|
||||
|
||||
#include <openssl_grpc/bio.h>
|
||||
|
||||
#if !defined(OPENSSL_TRUSTY)
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
|
||||
#if !defined(OPENSSL_WINDOWS)
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <unistd.h>
|
||||
#else
|
||||
OPENSSL_MSVC_PRAGMA(warning(push, 3))
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
OPENSSL_MSVC_PRAGMA(warning(pop))
|
||||
#endif
|
||||
|
||||
#include <openssl_grpc/err.h>
|
||||
#include <openssl_grpc/mem.h>
|
||||
|
||||
#include "internal.h"
|
||||
#include "../internal.h"
|
||||
|
||||
|
||||
enum {
|
||||
BIO_CONN_S_BEFORE,
|
||||
BIO_CONN_S_BLOCKED_CONNECT,
|
||||
BIO_CONN_S_OK,
|
||||
};
|
||||
|
||||
typedef struct bio_connect_st {
|
||||
int state;
|
||||
|
||||
char *param_hostname;
|
||||
char *param_port;
|
||||
int nbio;
|
||||
|
||||
unsigned short port;
|
||||
|
||||
struct sockaddr_storage them;
|
||||
socklen_t them_length;
|
||||
|
||||
// the file descriptor is kept in bio->num in order to match the socket
|
||||
// BIO.
|
||||
|
||||
// info_callback is called when the connection is initially made
|
||||
// callback(BIO,state,ret); The callback should return 'ret', state is for
|
||||
// compatibility with the SSL info_callback.
|
||||
int (*info_callback)(const BIO *bio, int state, int ret);
|
||||
} BIO_CONNECT;
|
||||
|
||||
#if !defined(OPENSSL_WINDOWS)
|
||||
static int closesocket(int sock) {
|
||||
return close(sock);
|
||||
}
|
||||
#endif
|
||||
|
||||
// split_host_and_port sets |*out_host| and |*out_port| to the host and port
|
||||
// parsed from |name|. It returns one on success or zero on error. Even when
|
||||
// successful, |*out_port| may be NULL on return if no port was specified.
|
||||
static int split_host_and_port(char **out_host, char **out_port, const char *name) {
|
||||
const char *host, *port = NULL;
|
||||
size_t host_len = 0;
|
||||
|
||||
*out_host = NULL;
|
||||
*out_port = NULL;
|
||||
|
||||
if (name[0] == '[') { // bracketed IPv6 address
|
||||
const char *close = strchr(name, ']');
|
||||
if (close == NULL) {
|
||||
return 0;
|
||||
}
|
||||
host = name + 1;
|
||||
host_len = close - host;
|
||||
if (close[1] == ':') { // [IP]:port
|
||||
port = close + 2;
|
||||
} else if (close[1] != 0) {
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
const char *colon = strchr(name, ':');
|
||||
if (colon == NULL || strchr(colon + 1, ':') != NULL) { // IPv6 address
|
||||
host = name;
|
||||
host_len = strlen(name);
|
||||
} else { // host:port
|
||||
host = name;
|
||||
host_len = colon - name;
|
||||
port = colon + 1;
|
||||
}
|
||||
}
|
||||
|
||||
*out_host = OPENSSL_strndup(host, host_len);
|
||||
if (*out_host == NULL) {
|
||||
return 0;
|
||||
}
|
||||
if (port == NULL) {
|
||||
*out_port = NULL;
|
||||
return 1;
|
||||
}
|
||||
*out_port = OPENSSL_strdup(port);
|
||||
if (*out_port == NULL) {
|
||||
OPENSSL_free(*out_host);
|
||||
*out_host = NULL;
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int conn_state(BIO *bio, BIO_CONNECT *c) {
|
||||
int ret = -1, i;
|
||||
int (*cb)(const BIO *, int, int) = NULL;
|
||||
|
||||
if (c->info_callback != NULL) {
|
||||
cb = c->info_callback;
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
switch (c->state) {
|
||||
case BIO_CONN_S_BEFORE:
|
||||
// If there's a hostname and a port, assume that both are
|
||||
// exactly what they say. If there is only a hostname, try
|
||||
// (just once) to split it into a hostname and port.
|
||||
|
||||
if (c->param_hostname == NULL) {
|
||||
OPENSSL_PUT_ERROR(BIO, BIO_R_NO_HOSTNAME_SPECIFIED);
|
||||
goto exit_loop;
|
||||
}
|
||||
|
||||
if (c->param_port == NULL) {
|
||||
char *host, *port;
|
||||
if (!split_host_and_port(&host, &port, c->param_hostname) ||
|
||||
port == NULL) {
|
||||
OPENSSL_free(host);
|
||||
OPENSSL_free(port);
|
||||
OPENSSL_PUT_ERROR(BIO, BIO_R_NO_PORT_SPECIFIED);
|
||||
ERR_add_error_data(2, "host=", c->param_hostname);
|
||||
goto exit_loop;
|
||||
}
|
||||
|
||||
OPENSSL_free(c->param_port);
|
||||
c->param_port = port;
|
||||
OPENSSL_free(c->param_hostname);
|
||||
c->param_hostname = host;
|
||||
}
|
||||
|
||||
if (!bio_ip_and_port_to_socket_and_addr(
|
||||
&bio->num, &c->them, &c->them_length, c->param_hostname,
|
||||
c->param_port)) {
|
||||
OPENSSL_PUT_ERROR(BIO, BIO_R_UNABLE_TO_CREATE_SOCKET);
|
||||
ERR_add_error_data(4, "host=", c->param_hostname, ":", c->param_port);
|
||||
goto exit_loop;
|
||||
}
|
||||
|
||||
if (c->nbio) {
|
||||
if (!bio_socket_nbio(bio->num, 1)) {
|
||||
OPENSSL_PUT_ERROR(BIO, BIO_R_ERROR_SETTING_NBIO);
|
||||
ERR_add_error_data(4, "host=", c->param_hostname, ":",
|
||||
c->param_port);
|
||||
goto exit_loop;
|
||||
}
|
||||
}
|
||||
|
||||
i = 1;
|
||||
ret = setsockopt(bio->num, SOL_SOCKET, SO_KEEPALIVE, (char *)&i,
|
||||
sizeof(i));
|
||||
if (ret < 0) {
|
||||
OPENSSL_PUT_SYSTEM_ERROR();
|
||||
OPENSSL_PUT_ERROR(BIO, BIO_R_KEEPALIVE);
|
||||
ERR_add_error_data(4, "host=", c->param_hostname, ":", c->param_port);
|
||||
goto exit_loop;
|
||||
}
|
||||
|
||||
BIO_clear_retry_flags(bio);
|
||||
ret = connect(bio->num, (struct sockaddr*) &c->them, c->them_length);
|
||||
if (ret < 0) {
|
||||
if (bio_fd_should_retry(ret)) {
|
||||
BIO_set_flags(bio, (BIO_FLAGS_IO_SPECIAL | BIO_FLAGS_SHOULD_RETRY));
|
||||
c->state = BIO_CONN_S_BLOCKED_CONNECT;
|
||||
bio->retry_reason = BIO_RR_CONNECT;
|
||||
} else {
|
||||
OPENSSL_PUT_SYSTEM_ERROR();
|
||||
OPENSSL_PUT_ERROR(BIO, BIO_R_CONNECT_ERROR);
|
||||
ERR_add_error_data(4, "host=", c->param_hostname, ":",
|
||||
c->param_port);
|
||||
}
|
||||
goto exit_loop;
|
||||
} else {
|
||||
c->state = BIO_CONN_S_OK;
|
||||
}
|
||||
break;
|
||||
|
||||
case BIO_CONN_S_BLOCKED_CONNECT:
|
||||
i = bio_sock_error(bio->num);
|
||||
if (i) {
|
||||
if (bio_fd_should_retry(ret)) {
|
||||
BIO_set_flags(bio, (BIO_FLAGS_IO_SPECIAL | BIO_FLAGS_SHOULD_RETRY));
|
||||
c->state = BIO_CONN_S_BLOCKED_CONNECT;
|
||||
bio->retry_reason = BIO_RR_CONNECT;
|
||||
ret = -1;
|
||||
} else {
|
||||
BIO_clear_retry_flags(bio);
|
||||
OPENSSL_PUT_SYSTEM_ERROR();
|
||||
OPENSSL_PUT_ERROR(BIO, BIO_R_NBIO_CONNECT_ERROR);
|
||||
ERR_add_error_data(4, "host=", c->param_hostname, ":", c->param_port);
|
||||
ret = 0;
|
||||
}
|
||||
goto exit_loop;
|
||||
} else {
|
||||
c->state = BIO_CONN_S_OK;
|
||||
}
|
||||
break;
|
||||
|
||||
case BIO_CONN_S_OK:
|
||||
ret = 1;
|
||||
goto exit_loop;
|
||||
default:
|
||||
assert(0);
|
||||
goto exit_loop;
|
||||
}
|
||||
|
||||
if (cb != NULL) {
|
||||
ret = cb((BIO *)bio, c->state, ret);
|
||||
if (ret == 0) {
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
exit_loop:
|
||||
if (cb != NULL) {
|
||||
ret = cb((BIO *)bio, c->state, ret);
|
||||
}
|
||||
|
||||
end:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static BIO_CONNECT *BIO_CONNECT_new(void) {
|
||||
BIO_CONNECT *ret = OPENSSL_malloc(sizeof(BIO_CONNECT));
|
||||
|
||||
if (ret == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
OPENSSL_memset(ret, 0, sizeof(BIO_CONNECT));
|
||||
|
||||
ret->state = BIO_CONN_S_BEFORE;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void BIO_CONNECT_free(BIO_CONNECT *c) {
|
||||
if (c == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
OPENSSL_free(c->param_hostname);
|
||||
OPENSSL_free(c->param_port);
|
||||
OPENSSL_free(c);
|
||||
}
|
||||
|
||||
static int conn_new(BIO *bio) {
|
||||
bio->init = 0;
|
||||
bio->num = -1;
|
||||
bio->flags = 0;
|
||||
bio->ptr = (char *)BIO_CONNECT_new();
|
||||
return bio->ptr != NULL;
|
||||
}
|
||||
|
||||
static void conn_close_socket(BIO *bio) {
|
||||
BIO_CONNECT *c = (BIO_CONNECT *) bio->ptr;
|
||||
|
||||
if (bio->num == -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Only do a shutdown if things were established
|
||||
if (c->state == BIO_CONN_S_OK) {
|
||||
shutdown(bio->num, 2);
|
||||
}
|
||||
closesocket(bio->num);
|
||||
bio->num = -1;
|
||||
}
|
||||
|
||||
static int conn_free(BIO *bio) {
|
||||
if (bio == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (bio->shutdown) {
|
||||
conn_close_socket(bio);
|
||||
}
|
||||
|
||||
BIO_CONNECT_free((BIO_CONNECT*) bio->ptr);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int conn_read(BIO *bio, char *out, int out_len) {
|
||||
int ret = 0;
|
||||
BIO_CONNECT *data;
|
||||
|
||||
data = (BIO_CONNECT *)bio->ptr;
|
||||
if (data->state != BIO_CONN_S_OK) {
|
||||
ret = conn_state(bio, data);
|
||||
if (ret <= 0) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
bio_clear_socket_error();
|
||||
ret = recv(bio->num, out, out_len, 0);
|
||||
BIO_clear_retry_flags(bio);
|
||||
if (ret <= 0) {
|
||||
if (bio_fd_should_retry(ret)) {
|
||||
BIO_set_retry_read(bio);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int conn_write(BIO *bio, const char *in, int in_len) {
|
||||
int ret;
|
||||
BIO_CONNECT *data;
|
||||
|
||||
data = (BIO_CONNECT *)bio->ptr;
|
||||
if (data->state != BIO_CONN_S_OK) {
|
||||
ret = conn_state(bio, data);
|
||||
if (ret <= 0) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
bio_clear_socket_error();
|
||||
ret = send(bio->num, in, in_len, 0);
|
||||
BIO_clear_retry_flags(bio);
|
||||
if (ret <= 0) {
|
||||
if (bio_fd_should_retry(ret)) {
|
||||
BIO_set_retry_write(bio);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static long conn_ctrl(BIO *bio, int cmd, long num, void *ptr) {
|
||||
int *ip;
|
||||
long ret = 1;
|
||||
BIO_CONNECT *data;
|
||||
|
||||
data = (BIO_CONNECT *)bio->ptr;
|
||||
|
||||
switch (cmd) {
|
||||
case BIO_CTRL_RESET:
|
||||
ret = 0;
|
||||
data->state = BIO_CONN_S_BEFORE;
|
||||
conn_close_socket(bio);
|
||||
bio->flags = 0;
|
||||
break;
|
||||
case BIO_C_DO_STATE_MACHINE:
|
||||
// use this one to start the connection
|
||||
if (data->state != BIO_CONN_S_OK) {
|
||||
ret = (long)conn_state(bio, data);
|
||||
} else {
|
||||
ret = 1;
|
||||
}
|
||||
break;
|
||||
case BIO_C_SET_CONNECT:
|
||||
if (ptr != NULL) {
|
||||
bio->init = 1;
|
||||
if (num == 0) {
|
||||
OPENSSL_free(data->param_hostname);
|
||||
data->param_hostname = OPENSSL_strdup(ptr);
|
||||
if (data->param_hostname == NULL) {
|
||||
ret = 0;
|
||||
}
|
||||
} else if (num == 1) {
|
||||
OPENSSL_free(data->param_port);
|
||||
data->param_port = OPENSSL_strdup(ptr);
|
||||
if (data->param_port == NULL) {
|
||||
ret = 0;
|
||||
}
|
||||
} else {
|
||||
ret = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case BIO_C_SET_NBIO:
|
||||
data->nbio = (int)num;
|
||||
break;
|
||||
case BIO_C_GET_FD:
|
||||
if (bio->init) {
|
||||
ip = (int *)ptr;
|
||||
if (ip != NULL) {
|
||||
*ip = bio->num;
|
||||
}
|
||||
ret = bio->num;
|
||||
} else {
|
||||
ret = -1;
|
||||
}
|
||||
break;
|
||||
case BIO_CTRL_GET_CLOSE:
|
||||
ret = bio->shutdown;
|
||||
break;
|
||||
case BIO_CTRL_SET_CLOSE:
|
||||
bio->shutdown = (int)num;
|
||||
break;
|
||||
case BIO_CTRL_PENDING:
|
||||
case BIO_CTRL_WPENDING:
|
||||
ret = 0;
|
||||
break;
|
||||
case BIO_CTRL_FLUSH:
|
||||
break;
|
||||
case BIO_CTRL_GET_CALLBACK: {
|
||||
int (**fptr)(const BIO *bio, int state, int xret);
|
||||
fptr = (int (**)(const BIO *bio, int state, int xret))ptr;
|
||||
*fptr = data->info_callback;
|
||||
} break;
|
||||
default:
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static long conn_callback_ctrl(BIO *bio, int cmd, bio_info_cb fp) {
|
||||
long ret = 1;
|
||||
BIO_CONNECT *data;
|
||||
|
||||
data = (BIO_CONNECT *)bio->ptr;
|
||||
|
||||
switch (cmd) {
|
||||
case BIO_CTRL_SET_CALLBACK:
|
||||
data->info_callback = (int (*)(const struct bio_st *, int, int))fp;
|
||||
break;
|
||||
default:
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
BIO *BIO_new_connect(const char *hostname) {
|
||||
BIO *ret;
|
||||
|
||||
ret = BIO_new(BIO_s_connect());
|
||||
if (ret == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
if (!BIO_set_conn_hostname(ret, hostname)) {
|
||||
BIO_free(ret);
|
||||
return NULL;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const BIO_METHOD methods_connectp = {
|
||||
BIO_TYPE_CONNECT, "socket connect", conn_write, conn_read,
|
||||
NULL /* puts */, NULL /* gets */, conn_ctrl, conn_new,
|
||||
conn_free, conn_callback_ctrl,
|
||||
};
|
||||
|
||||
const BIO_METHOD *BIO_s_connect(void) { return &methods_connectp; }
|
||||
|
||||
int BIO_set_conn_hostname(BIO *bio, const char *name) {
|
||||
return BIO_ctrl(bio, BIO_C_SET_CONNECT, 0, (void*) name);
|
||||
}
|
||||
|
||||
int BIO_set_conn_port(BIO *bio, const char *port_str) {
|
||||
return BIO_ctrl(bio, BIO_C_SET_CONNECT, 1, (void*) port_str);
|
||||
}
|
||||
|
||||
int BIO_set_conn_int_port(BIO *bio, const int *port) {
|
||||
char buf[DECIMAL_SIZE(int) + 1];
|
||||
BIO_snprintf(buf, sizeof(buf), "%d", *port);
|
||||
return BIO_set_conn_port(bio, buf);
|
||||
}
|
||||
|
||||
int BIO_set_nbio(BIO *bio, int on) {
|
||||
return BIO_ctrl(bio, BIO_C_SET_NBIO, on, NULL);
|
||||
}
|
||||
|
||||
int BIO_do_connect(BIO *bio) {
|
||||
return BIO_ctrl(bio, BIO_C_DO_STATE_MACHINE, 0, NULL);
|
||||
}
|
||||
|
||||
#endif // OPENSSL_TRUSTY
|
||||
+545
@@ -0,0 +1,545 @@
|
||||
/* Copyright (C) 1995-1998 Eric Young ([email protected])
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young ([email protected]).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson ([email protected]).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young ([email protected])"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson ([email protected])"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.] */
|
||||
|
||||
#include <openssl/bio.h>
|
||||
|
||||
#if !defined(OPENSSL_TRUSTY)
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
|
||||
#if !defined(OPENSSL_WINDOWS)
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <unistd.h>
|
||||
#else
|
||||
OPENSSL_MSVC_PRAGMA(warning(push, 3))
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
OPENSSL_MSVC_PRAGMA(warning(pop))
|
||||
#endif
|
||||
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/mem.h>
|
||||
|
||||
#include "internal.h"
|
||||
#include "../internal.h"
|
||||
|
||||
|
||||
enum {
|
||||
BIO_CONN_S_BEFORE,
|
||||
BIO_CONN_S_BLOCKED_CONNECT,
|
||||
BIO_CONN_S_OK,
|
||||
};
|
||||
|
||||
typedef struct bio_connect_st {
|
||||
int state;
|
||||
|
||||
char *param_hostname;
|
||||
char *param_port;
|
||||
int nbio;
|
||||
|
||||
unsigned short port;
|
||||
|
||||
struct sockaddr_storage them;
|
||||
socklen_t them_length;
|
||||
|
||||
// the file descriptor is kept in bio->num in order to match the socket
|
||||
// BIO.
|
||||
|
||||
// info_callback is called when the connection is initially made
|
||||
// callback(BIO,state,ret); The callback should return 'ret', state is for
|
||||
// compatibility with the SSL info_callback.
|
||||
int (*info_callback)(const BIO *bio, int state, int ret);
|
||||
} BIO_CONNECT;
|
||||
|
||||
#if !defined(OPENSSL_WINDOWS)
|
||||
static int closesocket(int sock) {
|
||||
return close(sock);
|
||||
}
|
||||
#endif
|
||||
|
||||
// split_host_and_port sets |*out_host| and |*out_port| to the host and port
|
||||
// parsed from |name|. It returns one on success or zero on error. Even when
|
||||
// successful, |*out_port| may be NULL on return if no port was specified.
|
||||
static int split_host_and_port(char **out_host, char **out_port, const char *name) {
|
||||
const char *host, *port = NULL;
|
||||
size_t host_len = 0;
|
||||
|
||||
*out_host = NULL;
|
||||
*out_port = NULL;
|
||||
|
||||
if (name[0] == '[') { // bracketed IPv6 address
|
||||
const char *close = strchr(name, ']');
|
||||
if (close == NULL) {
|
||||
return 0;
|
||||
}
|
||||
host = name + 1;
|
||||
host_len = close - host;
|
||||
if (close[1] == ':') { // [IP]:port
|
||||
port = close + 2;
|
||||
} else if (close[1] != 0) {
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
const char *colon = strchr(name, ':');
|
||||
if (colon == NULL || strchr(colon + 1, ':') != NULL) { // IPv6 address
|
||||
host = name;
|
||||
host_len = strlen(name);
|
||||
} else { // host:port
|
||||
host = name;
|
||||
host_len = colon - name;
|
||||
port = colon + 1;
|
||||
}
|
||||
}
|
||||
|
||||
*out_host = OPENSSL_strndup(host, host_len);
|
||||
if (*out_host == NULL) {
|
||||
return 0;
|
||||
}
|
||||
if (port == NULL) {
|
||||
*out_port = NULL;
|
||||
return 1;
|
||||
}
|
||||
*out_port = OPENSSL_strdup(port);
|
||||
if (*out_port == NULL) {
|
||||
OPENSSL_free(*out_host);
|
||||
*out_host = NULL;
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int conn_state(BIO *bio, BIO_CONNECT *c) {
|
||||
int ret = -1, i;
|
||||
int (*cb)(const BIO *, int, int) = NULL;
|
||||
|
||||
if (c->info_callback != NULL) {
|
||||
cb = c->info_callback;
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
switch (c->state) {
|
||||
case BIO_CONN_S_BEFORE:
|
||||
// If there's a hostname and a port, assume that both are
|
||||
// exactly what they say. If there is only a hostname, try
|
||||
// (just once) to split it into a hostname and port.
|
||||
|
||||
if (c->param_hostname == NULL) {
|
||||
OPENSSL_PUT_ERROR(BIO, BIO_R_NO_HOSTNAME_SPECIFIED);
|
||||
goto exit_loop;
|
||||
}
|
||||
|
||||
if (c->param_port == NULL) {
|
||||
char *host, *port;
|
||||
if (!split_host_and_port(&host, &port, c->param_hostname) ||
|
||||
port == NULL) {
|
||||
OPENSSL_free(host);
|
||||
OPENSSL_free(port);
|
||||
OPENSSL_PUT_ERROR(BIO, BIO_R_NO_PORT_SPECIFIED);
|
||||
ERR_add_error_data(2, "host=", c->param_hostname);
|
||||
goto exit_loop;
|
||||
}
|
||||
|
||||
OPENSSL_free(c->param_port);
|
||||
c->param_port = port;
|
||||
OPENSSL_free(c->param_hostname);
|
||||
c->param_hostname = host;
|
||||
}
|
||||
|
||||
if (!bio_ip_and_port_to_socket_and_addr(
|
||||
&bio->num, &c->them, &c->them_length, c->param_hostname,
|
||||
c->param_port)) {
|
||||
OPENSSL_PUT_ERROR(BIO, BIO_R_UNABLE_TO_CREATE_SOCKET);
|
||||
ERR_add_error_data(4, "host=", c->param_hostname, ":", c->param_port);
|
||||
goto exit_loop;
|
||||
}
|
||||
|
||||
if (c->nbio) {
|
||||
if (!bio_socket_nbio(bio->num, 1)) {
|
||||
OPENSSL_PUT_ERROR(BIO, BIO_R_ERROR_SETTING_NBIO);
|
||||
ERR_add_error_data(4, "host=", c->param_hostname, ":",
|
||||
c->param_port);
|
||||
goto exit_loop;
|
||||
}
|
||||
}
|
||||
|
||||
i = 1;
|
||||
ret = setsockopt(bio->num, SOL_SOCKET, SO_KEEPALIVE, (char *)&i,
|
||||
sizeof(i));
|
||||
if (ret < 0) {
|
||||
OPENSSL_PUT_SYSTEM_ERROR();
|
||||
OPENSSL_PUT_ERROR(BIO, BIO_R_KEEPALIVE);
|
||||
ERR_add_error_data(4, "host=", c->param_hostname, ":", c->param_port);
|
||||
goto exit_loop;
|
||||
}
|
||||
|
||||
BIO_clear_retry_flags(bio);
|
||||
ret = connect(bio->num, (struct sockaddr*) &c->them, c->them_length);
|
||||
if (ret < 0) {
|
||||
if (bio_fd_should_retry(ret)) {
|
||||
BIO_set_flags(bio, (BIO_FLAGS_IO_SPECIAL | BIO_FLAGS_SHOULD_RETRY));
|
||||
c->state = BIO_CONN_S_BLOCKED_CONNECT;
|
||||
bio->retry_reason = BIO_RR_CONNECT;
|
||||
} else {
|
||||
OPENSSL_PUT_SYSTEM_ERROR();
|
||||
OPENSSL_PUT_ERROR(BIO, BIO_R_CONNECT_ERROR);
|
||||
ERR_add_error_data(4, "host=", c->param_hostname, ":",
|
||||
c->param_port);
|
||||
}
|
||||
goto exit_loop;
|
||||
} else {
|
||||
c->state = BIO_CONN_S_OK;
|
||||
}
|
||||
break;
|
||||
|
||||
case BIO_CONN_S_BLOCKED_CONNECT:
|
||||
i = bio_sock_error(bio->num);
|
||||
if (i) {
|
||||
if (bio_fd_should_retry(ret)) {
|
||||
BIO_set_flags(bio, (BIO_FLAGS_IO_SPECIAL | BIO_FLAGS_SHOULD_RETRY));
|
||||
c->state = BIO_CONN_S_BLOCKED_CONNECT;
|
||||
bio->retry_reason = BIO_RR_CONNECT;
|
||||
ret = -1;
|
||||
} else {
|
||||
BIO_clear_retry_flags(bio);
|
||||
OPENSSL_PUT_SYSTEM_ERROR();
|
||||
OPENSSL_PUT_ERROR(BIO, BIO_R_NBIO_CONNECT_ERROR);
|
||||
ERR_add_error_data(4, "host=", c->param_hostname, ":", c->param_port);
|
||||
ret = 0;
|
||||
}
|
||||
goto exit_loop;
|
||||
} else {
|
||||
c->state = BIO_CONN_S_OK;
|
||||
}
|
||||
break;
|
||||
|
||||
case BIO_CONN_S_OK:
|
||||
ret = 1;
|
||||
goto exit_loop;
|
||||
default:
|
||||
assert(0);
|
||||
goto exit_loop;
|
||||
}
|
||||
|
||||
if (cb != NULL) {
|
||||
ret = cb((BIO *)bio, c->state, ret);
|
||||
if (ret == 0) {
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
exit_loop:
|
||||
if (cb != NULL) {
|
||||
ret = cb((BIO *)bio, c->state, ret);
|
||||
}
|
||||
|
||||
end:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static BIO_CONNECT *BIO_CONNECT_new(void) {
|
||||
BIO_CONNECT *ret = OPENSSL_malloc(sizeof(BIO_CONNECT));
|
||||
|
||||
if (ret == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
OPENSSL_memset(ret, 0, sizeof(BIO_CONNECT));
|
||||
|
||||
ret->state = BIO_CONN_S_BEFORE;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void BIO_CONNECT_free(BIO_CONNECT *c) {
|
||||
if (c == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
OPENSSL_free(c->param_hostname);
|
||||
OPENSSL_free(c->param_port);
|
||||
OPENSSL_free(c);
|
||||
}
|
||||
|
||||
static int conn_new(BIO *bio) {
|
||||
bio->init = 0;
|
||||
bio->num = -1;
|
||||
bio->flags = 0;
|
||||
bio->ptr = (char *)BIO_CONNECT_new();
|
||||
return bio->ptr != NULL;
|
||||
}
|
||||
|
||||
static void conn_close_socket(BIO *bio) {
|
||||
BIO_CONNECT *c = (BIO_CONNECT *) bio->ptr;
|
||||
|
||||
if (bio->num == -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Only do a shutdown if things were established
|
||||
if (c->state == BIO_CONN_S_OK) {
|
||||
shutdown(bio->num, 2);
|
||||
}
|
||||
closesocket(bio->num);
|
||||
bio->num = -1;
|
||||
}
|
||||
|
||||
static int conn_free(BIO *bio) {
|
||||
if (bio == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (bio->shutdown) {
|
||||
conn_close_socket(bio);
|
||||
}
|
||||
|
||||
BIO_CONNECT_free((BIO_CONNECT*) bio->ptr);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int conn_read(BIO *bio, char *out, int out_len) {
|
||||
int ret = 0;
|
||||
BIO_CONNECT *data;
|
||||
|
||||
data = (BIO_CONNECT *)bio->ptr;
|
||||
if (data->state != BIO_CONN_S_OK) {
|
||||
ret = conn_state(bio, data);
|
||||
if (ret <= 0) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
bio_clear_socket_error();
|
||||
ret = recv(bio->num, out, out_len, 0);
|
||||
BIO_clear_retry_flags(bio);
|
||||
if (ret <= 0) {
|
||||
if (bio_fd_should_retry(ret)) {
|
||||
BIO_set_retry_read(bio);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int conn_write(BIO *bio, const char *in, int in_len) {
|
||||
int ret;
|
||||
BIO_CONNECT *data;
|
||||
|
||||
data = (BIO_CONNECT *)bio->ptr;
|
||||
if (data->state != BIO_CONN_S_OK) {
|
||||
ret = conn_state(bio, data);
|
||||
if (ret <= 0) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
bio_clear_socket_error();
|
||||
ret = send(bio->num, in, in_len, 0);
|
||||
BIO_clear_retry_flags(bio);
|
||||
if (ret <= 0) {
|
||||
if (bio_fd_should_retry(ret)) {
|
||||
BIO_set_retry_write(bio);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static long conn_ctrl(BIO *bio, int cmd, long num, void *ptr) {
|
||||
int *ip;
|
||||
long ret = 1;
|
||||
BIO_CONNECT *data;
|
||||
|
||||
data = (BIO_CONNECT *)bio->ptr;
|
||||
|
||||
switch (cmd) {
|
||||
case BIO_CTRL_RESET:
|
||||
ret = 0;
|
||||
data->state = BIO_CONN_S_BEFORE;
|
||||
conn_close_socket(bio);
|
||||
bio->flags = 0;
|
||||
break;
|
||||
case BIO_C_DO_STATE_MACHINE:
|
||||
// use this one to start the connection
|
||||
if (data->state != BIO_CONN_S_OK) {
|
||||
ret = (long)conn_state(bio, data);
|
||||
} else {
|
||||
ret = 1;
|
||||
}
|
||||
break;
|
||||
case BIO_C_SET_CONNECT:
|
||||
if (ptr != NULL) {
|
||||
bio->init = 1;
|
||||
if (num == 0) {
|
||||
OPENSSL_free(data->param_hostname);
|
||||
data->param_hostname = OPENSSL_strdup(ptr);
|
||||
if (data->param_hostname == NULL) {
|
||||
ret = 0;
|
||||
}
|
||||
} else if (num == 1) {
|
||||
OPENSSL_free(data->param_port);
|
||||
data->param_port = OPENSSL_strdup(ptr);
|
||||
if (data->param_port == NULL) {
|
||||
ret = 0;
|
||||
}
|
||||
} else {
|
||||
ret = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case BIO_C_SET_NBIO:
|
||||
data->nbio = (int)num;
|
||||
break;
|
||||
case BIO_C_GET_FD:
|
||||
if (bio->init) {
|
||||
ip = (int *)ptr;
|
||||
if (ip != NULL) {
|
||||
*ip = bio->num;
|
||||
}
|
||||
ret = bio->num;
|
||||
} else {
|
||||
ret = -1;
|
||||
}
|
||||
break;
|
||||
case BIO_CTRL_GET_CLOSE:
|
||||
ret = bio->shutdown;
|
||||
break;
|
||||
case BIO_CTRL_SET_CLOSE:
|
||||
bio->shutdown = (int)num;
|
||||
break;
|
||||
case BIO_CTRL_PENDING:
|
||||
case BIO_CTRL_WPENDING:
|
||||
ret = 0;
|
||||
break;
|
||||
case BIO_CTRL_FLUSH:
|
||||
break;
|
||||
case BIO_CTRL_GET_CALLBACK: {
|
||||
int (**fptr)(const BIO *bio, int state, int xret);
|
||||
fptr = (int (**)(const BIO *bio, int state, int xret))ptr;
|
||||
*fptr = data->info_callback;
|
||||
} break;
|
||||
default:
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static long conn_callback_ctrl(BIO *bio, int cmd, bio_info_cb fp) {
|
||||
long ret = 1;
|
||||
BIO_CONNECT *data;
|
||||
|
||||
data = (BIO_CONNECT *)bio->ptr;
|
||||
|
||||
switch (cmd) {
|
||||
case BIO_CTRL_SET_CALLBACK:
|
||||
data->info_callback = (int (*)(const struct bio_st *, int, int))fp;
|
||||
break;
|
||||
default:
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
BIO *BIO_new_connect(const char *hostname) {
|
||||
BIO *ret;
|
||||
|
||||
ret = BIO_new(BIO_s_connect());
|
||||
if (ret == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
if (!BIO_set_conn_hostname(ret, hostname)) {
|
||||
BIO_free(ret);
|
||||
return NULL;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const BIO_METHOD methods_connectp = {
|
||||
BIO_TYPE_CONNECT, "socket connect", conn_write, conn_read,
|
||||
NULL /* puts */, NULL /* gets */, conn_ctrl, conn_new,
|
||||
conn_free, conn_callback_ctrl,
|
||||
};
|
||||
|
||||
const BIO_METHOD *BIO_s_connect(void) { return &methods_connectp; }
|
||||
|
||||
int BIO_set_conn_hostname(BIO *bio, const char *name) {
|
||||
return BIO_ctrl(bio, BIO_C_SET_CONNECT, 0, (void*) name);
|
||||
}
|
||||
|
||||
int BIO_set_conn_port(BIO *bio, const char *port_str) {
|
||||
return BIO_ctrl(bio, BIO_C_SET_CONNECT, 1, (void*) port_str);
|
||||
}
|
||||
|
||||
int BIO_set_conn_int_port(BIO *bio, const int *port) {
|
||||
char buf[DECIMAL_SIZE(int) + 1];
|
||||
BIO_snprintf(buf, sizeof(buf), "%d", *port);
|
||||
return BIO_set_conn_port(bio, buf);
|
||||
}
|
||||
|
||||
int BIO_set_nbio(BIO *bio, int on) {
|
||||
return BIO_ctrl(bio, BIO_C_SET_NBIO, on, NULL);
|
||||
}
|
||||
|
||||
int BIO_do_connect(BIO *bio) {
|
||||
return BIO_ctrl(bio, BIO_C_DO_STATE_MACHINE, 0, NULL);
|
||||
}
|
||||
|
||||
#endif // OPENSSL_TRUSTY
|
||||
Generated
+279
@@ -0,0 +1,279 @@
|
||||
/* Copyright (C) 1995-1998 Eric Young ([email protected])
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young ([email protected]).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson ([email protected]).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young ([email protected])"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson ([email protected])"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.] */
|
||||
|
||||
#include <openssl_grpc/bio.h>
|
||||
|
||||
#if !defined(OPENSSL_TRUSTY)
|
||||
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
|
||||
#if !defined(OPENSSL_WINDOWS)
|
||||
#include <unistd.h>
|
||||
#else
|
||||
#include <io.h>
|
||||
OPENSSL_MSVC_PRAGMA(warning(push, 3))
|
||||
#include <windows.h>
|
||||
OPENSSL_MSVC_PRAGMA(warning(pop))
|
||||
#endif
|
||||
|
||||
#include <openssl_grpc/err.h>
|
||||
#include <openssl_grpc/mem.h>
|
||||
|
||||
#include "internal.h"
|
||||
#include "../internal.h"
|
||||
|
||||
|
||||
static int bio_fd_non_fatal_error(int err) {
|
||||
if (
|
||||
#ifdef EWOULDBLOCK
|
||||
err == EWOULDBLOCK ||
|
||||
#endif
|
||||
#ifdef WSAEWOULDBLOCK
|
||||
err == WSAEWOULDBLOCK ||
|
||||
#endif
|
||||
#ifdef ENOTCONN
|
||||
err == ENOTCONN ||
|
||||
#endif
|
||||
#ifdef EINTR
|
||||
err == EINTR ||
|
||||
#endif
|
||||
#ifdef EAGAIN
|
||||
err == EAGAIN ||
|
||||
#endif
|
||||
#ifdef EPROTO
|
||||
err == EPROTO ||
|
||||
#endif
|
||||
#ifdef EINPROGRESS
|
||||
err == EINPROGRESS ||
|
||||
#endif
|
||||
#ifdef EALREADY
|
||||
err == EALREADY ||
|
||||
#endif
|
||||
0) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined(OPENSSL_WINDOWS)
|
||||
#define BORINGSSL_ERRNO (int)GetLastError()
|
||||
#define BORINGSSL_CLOSE _close
|
||||
#define BORINGSSL_LSEEK _lseek
|
||||
#define BORINGSSL_READ _read
|
||||
#define BORINGSSL_WRITE _write
|
||||
#else
|
||||
#define BORINGSSL_ERRNO errno
|
||||
#define BORINGSSL_CLOSE close
|
||||
#define BORINGSSL_LSEEK lseek
|
||||
#define BORINGSSL_READ read
|
||||
#define BORINGSSL_WRITE write
|
||||
#endif
|
||||
|
||||
int bio_fd_should_retry(int i) {
|
||||
if (i == -1) {
|
||||
return bio_fd_non_fatal_error(BORINGSSL_ERRNO);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
BIO *BIO_new_fd(int fd, int close_flag) {
|
||||
BIO *ret = BIO_new(BIO_s_fd());
|
||||
if (ret == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
BIO_set_fd(ret, fd, close_flag);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int fd_new(BIO *bio) {
|
||||
// num is used to store the file descriptor.
|
||||
bio->num = -1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int fd_free(BIO *bio) {
|
||||
if (bio == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (bio->shutdown) {
|
||||
if (bio->init) {
|
||||
BORINGSSL_CLOSE(bio->num);
|
||||
}
|
||||
bio->init = 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int fd_read(BIO *b, char *out, int outl) {
|
||||
int ret = 0;
|
||||
|
||||
ret = BORINGSSL_READ(b->num, out, outl);
|
||||
BIO_clear_retry_flags(b);
|
||||
if (ret <= 0) {
|
||||
if (bio_fd_should_retry(ret)) {
|
||||
BIO_set_retry_read(b);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int fd_write(BIO *b, const char *in, int inl) {
|
||||
int ret = BORINGSSL_WRITE(b->num, in, inl);
|
||||
BIO_clear_retry_flags(b);
|
||||
if (ret <= 0) {
|
||||
if (bio_fd_should_retry(ret)) {
|
||||
BIO_set_retry_write(b);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static long fd_ctrl(BIO *b, int cmd, long num, void *ptr) {
|
||||
long ret = 1;
|
||||
int *ip;
|
||||
|
||||
switch (cmd) {
|
||||
case BIO_CTRL_RESET:
|
||||
num = 0;
|
||||
OPENSSL_FALLTHROUGH;
|
||||
case BIO_C_FILE_SEEK:
|
||||
ret = 0;
|
||||
if (b->init) {
|
||||
ret = (long)BORINGSSL_LSEEK(b->num, num, SEEK_SET);
|
||||
}
|
||||
break;
|
||||
case BIO_C_FILE_TELL:
|
||||
case BIO_CTRL_INFO:
|
||||
ret = 0;
|
||||
if (b->init) {
|
||||
ret = (long)BORINGSSL_LSEEK(b->num, 0, SEEK_CUR);
|
||||
}
|
||||
break;
|
||||
case BIO_C_SET_FD:
|
||||
fd_free(b);
|
||||
b->num = *((int *)ptr);
|
||||
b->shutdown = (int)num;
|
||||
b->init = 1;
|
||||
break;
|
||||
case BIO_C_GET_FD:
|
||||
if (b->init) {
|
||||
ip = (int *)ptr;
|
||||
if (ip != NULL) {
|
||||
*ip = b->num;
|
||||
}
|
||||
return b->num;
|
||||
} else {
|
||||
ret = -1;
|
||||
}
|
||||
break;
|
||||
case BIO_CTRL_GET_CLOSE:
|
||||
ret = b->shutdown;
|
||||
break;
|
||||
case BIO_CTRL_SET_CLOSE:
|
||||
b->shutdown = (int)num;
|
||||
break;
|
||||
case BIO_CTRL_PENDING:
|
||||
case BIO_CTRL_WPENDING:
|
||||
ret = 0;
|
||||
break;
|
||||
case BIO_CTRL_FLUSH:
|
||||
ret = 1;
|
||||
break;
|
||||
default:
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int fd_gets(BIO *bp, char *buf, int size) {
|
||||
char *ptr = buf;
|
||||
char *end = buf + size - 1;
|
||||
|
||||
if (size <= 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
while (ptr < end && fd_read(bp, ptr, 1) > 0 && ptr[0] != '\n') {
|
||||
ptr++;
|
||||
}
|
||||
|
||||
ptr[0] = '\0';
|
||||
|
||||
return ptr - buf;
|
||||
}
|
||||
|
||||
static const BIO_METHOD methods_fdp = {
|
||||
BIO_TYPE_FD, "file descriptor", fd_write, fd_read, NULL /* puts */,
|
||||
fd_gets, fd_ctrl, fd_new, fd_free, NULL /* callback_ctrl */,
|
||||
};
|
||||
|
||||
const BIO_METHOD *BIO_s_fd(void) { return &methods_fdp; }
|
||||
|
||||
int BIO_set_fd(BIO *bio, int fd, int close_flag) {
|
||||
return BIO_int_ctrl(bio, BIO_C_SET_FD, close_flag, fd);
|
||||
}
|
||||
|
||||
int BIO_get_fd(BIO *bio, int *out_fd) {
|
||||
return BIO_ctrl(bio, BIO_C_GET_FD, 0, (char *) out_fd);
|
||||
}
|
||||
|
||||
#endif // OPENSSL_TRUSTY
|
||||
+279
@@ -0,0 +1,279 @@
|
||||
/* Copyright (C) 1995-1998 Eric Young ([email protected])
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young ([email protected]).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson ([email protected]).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young ([email protected])"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson ([email protected])"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.] */
|
||||
|
||||
#include <openssl/bio.h>
|
||||
|
||||
#if !defined(OPENSSL_TRUSTY)
|
||||
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
|
||||
#if !defined(OPENSSL_WINDOWS)
|
||||
#include <unistd.h>
|
||||
#else
|
||||
#include <io.h>
|
||||
OPENSSL_MSVC_PRAGMA(warning(push, 3))
|
||||
#include <windows.h>
|
||||
OPENSSL_MSVC_PRAGMA(warning(pop))
|
||||
#endif
|
||||
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/mem.h>
|
||||
|
||||
#include "internal.h"
|
||||
#include "../internal.h"
|
||||
|
||||
|
||||
static int bio_fd_non_fatal_error(int err) {
|
||||
if (
|
||||
#ifdef EWOULDBLOCK
|
||||
err == EWOULDBLOCK ||
|
||||
#endif
|
||||
#ifdef WSAEWOULDBLOCK
|
||||
err == WSAEWOULDBLOCK ||
|
||||
#endif
|
||||
#ifdef ENOTCONN
|
||||
err == ENOTCONN ||
|
||||
#endif
|
||||
#ifdef EINTR
|
||||
err == EINTR ||
|
||||
#endif
|
||||
#ifdef EAGAIN
|
||||
err == EAGAIN ||
|
||||
#endif
|
||||
#ifdef EPROTO
|
||||
err == EPROTO ||
|
||||
#endif
|
||||
#ifdef EINPROGRESS
|
||||
err == EINPROGRESS ||
|
||||
#endif
|
||||
#ifdef EALREADY
|
||||
err == EALREADY ||
|
||||
#endif
|
||||
0) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined(OPENSSL_WINDOWS)
|
||||
#define BORINGSSL_ERRNO (int)GetLastError()
|
||||
#define BORINGSSL_CLOSE _close
|
||||
#define BORINGSSL_LSEEK _lseek
|
||||
#define BORINGSSL_READ _read
|
||||
#define BORINGSSL_WRITE _write
|
||||
#else
|
||||
#define BORINGSSL_ERRNO errno
|
||||
#define BORINGSSL_CLOSE close
|
||||
#define BORINGSSL_LSEEK lseek
|
||||
#define BORINGSSL_READ read
|
||||
#define BORINGSSL_WRITE write
|
||||
#endif
|
||||
|
||||
int bio_fd_should_retry(int i) {
|
||||
if (i == -1) {
|
||||
return bio_fd_non_fatal_error(BORINGSSL_ERRNO);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
BIO *BIO_new_fd(int fd, int close_flag) {
|
||||
BIO *ret = BIO_new(BIO_s_fd());
|
||||
if (ret == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
BIO_set_fd(ret, fd, close_flag);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int fd_new(BIO *bio) {
|
||||
// num is used to store the file descriptor.
|
||||
bio->num = -1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int fd_free(BIO *bio) {
|
||||
if (bio == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (bio->shutdown) {
|
||||
if (bio->init) {
|
||||
BORINGSSL_CLOSE(bio->num);
|
||||
}
|
||||
bio->init = 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int fd_read(BIO *b, char *out, int outl) {
|
||||
int ret = 0;
|
||||
|
||||
ret = BORINGSSL_READ(b->num, out, outl);
|
||||
BIO_clear_retry_flags(b);
|
||||
if (ret <= 0) {
|
||||
if (bio_fd_should_retry(ret)) {
|
||||
BIO_set_retry_read(b);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int fd_write(BIO *b, const char *in, int inl) {
|
||||
int ret = BORINGSSL_WRITE(b->num, in, inl);
|
||||
BIO_clear_retry_flags(b);
|
||||
if (ret <= 0) {
|
||||
if (bio_fd_should_retry(ret)) {
|
||||
BIO_set_retry_write(b);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static long fd_ctrl(BIO *b, int cmd, long num, void *ptr) {
|
||||
long ret = 1;
|
||||
int *ip;
|
||||
|
||||
switch (cmd) {
|
||||
case BIO_CTRL_RESET:
|
||||
num = 0;
|
||||
OPENSSL_FALLTHROUGH;
|
||||
case BIO_C_FILE_SEEK:
|
||||
ret = 0;
|
||||
if (b->init) {
|
||||
ret = (long)BORINGSSL_LSEEK(b->num, num, SEEK_SET);
|
||||
}
|
||||
break;
|
||||
case BIO_C_FILE_TELL:
|
||||
case BIO_CTRL_INFO:
|
||||
ret = 0;
|
||||
if (b->init) {
|
||||
ret = (long)BORINGSSL_LSEEK(b->num, 0, SEEK_CUR);
|
||||
}
|
||||
break;
|
||||
case BIO_C_SET_FD:
|
||||
fd_free(b);
|
||||
b->num = *((int *)ptr);
|
||||
b->shutdown = (int)num;
|
||||
b->init = 1;
|
||||
break;
|
||||
case BIO_C_GET_FD:
|
||||
if (b->init) {
|
||||
ip = (int *)ptr;
|
||||
if (ip != NULL) {
|
||||
*ip = b->num;
|
||||
}
|
||||
return b->num;
|
||||
} else {
|
||||
ret = -1;
|
||||
}
|
||||
break;
|
||||
case BIO_CTRL_GET_CLOSE:
|
||||
ret = b->shutdown;
|
||||
break;
|
||||
case BIO_CTRL_SET_CLOSE:
|
||||
b->shutdown = (int)num;
|
||||
break;
|
||||
case BIO_CTRL_PENDING:
|
||||
case BIO_CTRL_WPENDING:
|
||||
ret = 0;
|
||||
break;
|
||||
case BIO_CTRL_FLUSH:
|
||||
ret = 1;
|
||||
break;
|
||||
default:
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int fd_gets(BIO *bp, char *buf, int size) {
|
||||
char *ptr = buf;
|
||||
char *end = buf + size - 1;
|
||||
|
||||
if (size <= 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
while (ptr < end && fd_read(bp, ptr, 1) > 0 && ptr[0] != '\n') {
|
||||
ptr++;
|
||||
}
|
||||
|
||||
ptr[0] = '\0';
|
||||
|
||||
return ptr - buf;
|
||||
}
|
||||
|
||||
static const BIO_METHOD methods_fdp = {
|
||||
BIO_TYPE_FD, "file descriptor", fd_write, fd_read, NULL /* puts */,
|
||||
fd_gets, fd_ctrl, fd_new, fd_free, NULL /* callback_ctrl */,
|
||||
};
|
||||
|
||||
const BIO_METHOD *BIO_s_fd(void) { return &methods_fdp; }
|
||||
|
||||
int BIO_set_fd(BIO *bio, int fd, int close_flag) {
|
||||
return BIO_int_ctrl(bio, BIO_C_SET_FD, close_flag, fd);
|
||||
}
|
||||
|
||||
int BIO_get_fd(BIO *bio, int *out_fd) {
|
||||
return BIO_ctrl(bio, BIO_C_GET_FD, 0, (char *) out_fd);
|
||||
}
|
||||
|
||||
#endif // OPENSSL_TRUSTY
|
||||
+317
@@ -0,0 +1,317 @@
|
||||
/* Copyright (C) 1995-1998 Eric Young ([email protected])
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young ([email protected]).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson ([email protected]).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young ([email protected])"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson ([email protected])"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.] */
|
||||
|
||||
#if defined(__linux) || defined(__sun) || defined(__hpux)
|
||||
// Following definition aliases fopen to fopen64 on above mentioned
|
||||
// platforms. This makes it possible to open and sequentially access
|
||||
// files larger than 2GB from 32-bit application. It does not allow to
|
||||
// traverse them beyond 2GB with fseek/ftell, but on the other hand *no*
|
||||
// 32-bit platform permits that, not with fseek/ftell. Not to mention
|
||||
// that breaking 2GB limit for seeking would require surgery to *our*
|
||||
// API. But sequential access suffices for practical cases when you
|
||||
// can run into large files, such as fingerprinting, so we can let API
|
||||
// alone. For reference, the list of 32-bit platforms which allow for
|
||||
// sequential access of large files without extra "magic" comprise *BSD,
|
||||
// Darwin, IRIX...
|
||||
#ifndef _FILE_OFFSET_BITS
|
||||
#define _FILE_OFFSET_BITS 64
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include <openssl_grpc/bio.h>
|
||||
|
||||
#if !defined(OPENSSL_TRUSTY)
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <openssl_grpc/err.h>
|
||||
#include <openssl_grpc/mem.h>
|
||||
|
||||
#include "../internal.h"
|
||||
|
||||
|
||||
#define BIO_FP_READ 0x02
|
||||
#define BIO_FP_WRITE 0x04
|
||||
#define BIO_FP_APPEND 0x08
|
||||
|
||||
BIO *BIO_new_file(const char *filename, const char *mode) {
|
||||
BIO *ret;
|
||||
FILE *file;
|
||||
|
||||
file = fopen(filename, mode);
|
||||
if (file == NULL) {
|
||||
OPENSSL_PUT_SYSTEM_ERROR();
|
||||
|
||||
ERR_add_error_data(5, "fopen('", filename, "','", mode, "')");
|
||||
if (errno == ENOENT) {
|
||||
OPENSSL_PUT_ERROR(BIO, BIO_R_NO_SUCH_FILE);
|
||||
} else {
|
||||
OPENSSL_PUT_ERROR(BIO, BIO_R_SYS_LIB);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ret = BIO_new_fp(file, BIO_CLOSE);
|
||||
if (ret == NULL) {
|
||||
fclose(file);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
BIO *BIO_new_fp(FILE *stream, int close_flag) {
|
||||
BIO *ret = BIO_new(BIO_s_file());
|
||||
|
||||
if (ret == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
BIO_set_fp(ret, stream, close_flag);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int file_new(BIO *bio) { return 1; }
|
||||
|
||||
static int file_free(BIO *bio) {
|
||||
if (bio == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!bio->shutdown) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (bio->init && bio->ptr != NULL) {
|
||||
fclose(bio->ptr);
|
||||
bio->ptr = NULL;
|
||||
}
|
||||
bio->init = 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int file_read(BIO *b, char *out, int outl) {
|
||||
if (!b->init) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t ret = fread(out, 1, outl, (FILE *)b->ptr);
|
||||
if (ret == 0 && ferror((FILE *)b->ptr)) {
|
||||
OPENSSL_PUT_SYSTEM_ERROR();
|
||||
OPENSSL_PUT_ERROR(BIO, ERR_R_SYS_LIB);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// fread reads at most |outl| bytes, so |ret| fits in an int.
|
||||
return (int)ret;
|
||||
}
|
||||
|
||||
static int file_write(BIO *b, const char *in, int inl) {
|
||||
int ret = 0;
|
||||
|
||||
if (!b->init) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = fwrite(in, inl, 1, (FILE *)b->ptr);
|
||||
if (ret > 0) {
|
||||
ret = inl;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static long file_ctrl(BIO *b, int cmd, long num, void *ptr) {
|
||||
long ret = 1;
|
||||
FILE *fp = (FILE *)b->ptr;
|
||||
FILE **fpp;
|
||||
char p[4];
|
||||
|
||||
switch (cmd) {
|
||||
case BIO_CTRL_RESET:
|
||||
num = 0;
|
||||
OPENSSL_FALLTHROUGH;
|
||||
case BIO_C_FILE_SEEK:
|
||||
ret = (long)fseek(fp, num, 0);
|
||||
break;
|
||||
case BIO_CTRL_EOF:
|
||||
ret = (long)feof(fp);
|
||||
break;
|
||||
case BIO_C_FILE_TELL:
|
||||
case BIO_CTRL_INFO:
|
||||
ret = ftell(fp);
|
||||
break;
|
||||
case BIO_C_SET_FILE_PTR:
|
||||
file_free(b);
|
||||
b->shutdown = (int)num & BIO_CLOSE;
|
||||
b->ptr = ptr;
|
||||
b->init = 1;
|
||||
break;
|
||||
case BIO_C_SET_FILENAME:
|
||||
file_free(b);
|
||||
b->shutdown = (int)num & BIO_CLOSE;
|
||||
if (num & BIO_FP_APPEND) {
|
||||
if (num & BIO_FP_READ) {
|
||||
OPENSSL_strlcpy(p, "a+", sizeof(p));
|
||||
} else {
|
||||
OPENSSL_strlcpy(p, "a", sizeof(p));
|
||||
}
|
||||
} else if ((num & BIO_FP_READ) && (num & BIO_FP_WRITE)) {
|
||||
OPENSSL_strlcpy(p, "r+", sizeof(p));
|
||||
} else if (num & BIO_FP_WRITE) {
|
||||
OPENSSL_strlcpy(p, "w", sizeof(p));
|
||||
} else if (num & BIO_FP_READ) {
|
||||
OPENSSL_strlcpy(p, "r", sizeof(p));
|
||||
} else {
|
||||
OPENSSL_PUT_ERROR(BIO, BIO_R_BAD_FOPEN_MODE);
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
fp = fopen(ptr, p);
|
||||
if (fp == NULL) {
|
||||
OPENSSL_PUT_SYSTEM_ERROR();
|
||||
ERR_add_error_data(5, "fopen('", ptr, "','", p, "')");
|
||||
OPENSSL_PUT_ERROR(BIO, ERR_R_SYS_LIB);
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
b->ptr = fp;
|
||||
b->init = 1;
|
||||
break;
|
||||
case BIO_C_GET_FILE_PTR:
|
||||
// the ptr parameter is actually a FILE ** in this case.
|
||||
if (ptr != NULL) {
|
||||
fpp = (FILE **)ptr;
|
||||
*fpp = (FILE *)b->ptr;
|
||||
}
|
||||
break;
|
||||
case BIO_CTRL_GET_CLOSE:
|
||||
ret = (long)b->shutdown;
|
||||
break;
|
||||
case BIO_CTRL_SET_CLOSE:
|
||||
b->shutdown = (int)num;
|
||||
break;
|
||||
case BIO_CTRL_FLUSH:
|
||||
ret = 0 == fflush((FILE *)b->ptr);
|
||||
break;
|
||||
case BIO_CTRL_WPENDING:
|
||||
case BIO_CTRL_PENDING:
|
||||
default:
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int file_gets(BIO *bp, char *buf, int size) {
|
||||
int ret = 0;
|
||||
|
||||
if (size == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!fgets(buf, size, (FILE *)bp->ptr)) {
|
||||
buf[0] = 0;
|
||||
goto err;
|
||||
}
|
||||
ret = strlen(buf);
|
||||
|
||||
err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const BIO_METHOD methods_filep = {
|
||||
BIO_TYPE_FILE, "FILE pointer",
|
||||
file_write, file_read,
|
||||
NULL /* puts */, file_gets,
|
||||
file_ctrl, file_new,
|
||||
file_free, NULL /* callback_ctrl */,
|
||||
};
|
||||
|
||||
const BIO_METHOD *BIO_s_file(void) { return &methods_filep; }
|
||||
|
||||
|
||||
int BIO_get_fp(BIO *bio, FILE **out_file) {
|
||||
return BIO_ctrl(bio, BIO_C_GET_FILE_PTR, 0, (char*) out_file);
|
||||
}
|
||||
|
||||
int BIO_set_fp(BIO *bio, FILE *file, int close_flag) {
|
||||
return BIO_ctrl(bio, BIO_C_SET_FILE_PTR, close_flag, (char *) file);
|
||||
}
|
||||
|
||||
int BIO_read_filename(BIO *bio, const char *filename) {
|
||||
return BIO_ctrl(bio, BIO_C_SET_FILENAME, BIO_CLOSE | BIO_FP_READ,
|
||||
(char *)filename);
|
||||
}
|
||||
|
||||
int BIO_write_filename(BIO *bio, const char *filename) {
|
||||
return BIO_ctrl(bio, BIO_C_SET_FILENAME, BIO_CLOSE | BIO_FP_WRITE,
|
||||
(char *)filename);
|
||||
}
|
||||
|
||||
int BIO_append_filename(BIO *bio, const char *filename) {
|
||||
return BIO_ctrl(bio, BIO_C_SET_FILENAME, BIO_CLOSE | BIO_FP_APPEND,
|
||||
(char *)filename);
|
||||
}
|
||||
|
||||
int BIO_rw_filename(BIO *bio, const char *filename) {
|
||||
return BIO_ctrl(bio, BIO_C_SET_FILENAME,
|
||||
BIO_CLOSE | BIO_FP_READ | BIO_FP_WRITE, (char *)filename);
|
||||
}
|
||||
|
||||
#endif // OPENSSL_TRUSTY
|
||||
+317
@@ -0,0 +1,317 @@
|
||||
/* Copyright (C) 1995-1998 Eric Young ([email protected])
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young ([email protected]).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson ([email protected]).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young ([email protected])"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson ([email protected])"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.] */
|
||||
|
||||
#if defined(__linux) || defined(__sun) || defined(__hpux)
|
||||
// Following definition aliases fopen to fopen64 on above mentioned
|
||||
// platforms. This makes it possible to open and sequentially access
|
||||
// files larger than 2GB from 32-bit application. It does not allow to
|
||||
// traverse them beyond 2GB with fseek/ftell, but on the other hand *no*
|
||||
// 32-bit platform permits that, not with fseek/ftell. Not to mention
|
||||
// that breaking 2GB limit for seeking would require surgery to *our*
|
||||
// API. But sequential access suffices for practical cases when you
|
||||
// can run into large files, such as fingerprinting, so we can let API
|
||||
// alone. For reference, the list of 32-bit platforms which allow for
|
||||
// sequential access of large files without extra "magic" comprise *BSD,
|
||||
// Darwin, IRIX...
|
||||
#ifndef _FILE_OFFSET_BITS
|
||||
#define _FILE_OFFSET_BITS 64
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include <openssl/bio.h>
|
||||
|
||||
#if !defined(OPENSSL_TRUSTY)
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/mem.h>
|
||||
|
||||
#include "../internal.h"
|
||||
|
||||
|
||||
#define BIO_FP_READ 0x02
|
||||
#define BIO_FP_WRITE 0x04
|
||||
#define BIO_FP_APPEND 0x08
|
||||
|
||||
BIO *BIO_new_file(const char *filename, const char *mode) {
|
||||
BIO *ret;
|
||||
FILE *file;
|
||||
|
||||
file = fopen(filename, mode);
|
||||
if (file == NULL) {
|
||||
OPENSSL_PUT_SYSTEM_ERROR();
|
||||
|
||||
ERR_add_error_data(5, "fopen('", filename, "','", mode, "')");
|
||||
if (errno == ENOENT) {
|
||||
OPENSSL_PUT_ERROR(BIO, BIO_R_NO_SUCH_FILE);
|
||||
} else {
|
||||
OPENSSL_PUT_ERROR(BIO, BIO_R_SYS_LIB);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ret = BIO_new_fp(file, BIO_CLOSE);
|
||||
if (ret == NULL) {
|
||||
fclose(file);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
BIO *BIO_new_fp(FILE *stream, int close_flag) {
|
||||
BIO *ret = BIO_new(BIO_s_file());
|
||||
|
||||
if (ret == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
BIO_set_fp(ret, stream, close_flag);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int file_new(BIO *bio) { return 1; }
|
||||
|
||||
static int file_free(BIO *bio) {
|
||||
if (bio == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!bio->shutdown) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (bio->init && bio->ptr != NULL) {
|
||||
fclose(bio->ptr);
|
||||
bio->ptr = NULL;
|
||||
}
|
||||
bio->init = 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int file_read(BIO *b, char *out, int outl) {
|
||||
if (!b->init) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t ret = fread(out, 1, outl, (FILE *)b->ptr);
|
||||
if (ret == 0 && ferror((FILE *)b->ptr)) {
|
||||
OPENSSL_PUT_SYSTEM_ERROR();
|
||||
OPENSSL_PUT_ERROR(BIO, ERR_R_SYS_LIB);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// fread reads at most |outl| bytes, so |ret| fits in an int.
|
||||
return (int)ret;
|
||||
}
|
||||
|
||||
static int file_write(BIO *b, const char *in, int inl) {
|
||||
int ret = 0;
|
||||
|
||||
if (!b->init) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = fwrite(in, inl, 1, (FILE *)b->ptr);
|
||||
if (ret > 0) {
|
||||
ret = inl;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static long file_ctrl(BIO *b, int cmd, long num, void *ptr) {
|
||||
long ret = 1;
|
||||
FILE *fp = (FILE *)b->ptr;
|
||||
FILE **fpp;
|
||||
char p[4];
|
||||
|
||||
switch (cmd) {
|
||||
case BIO_CTRL_RESET:
|
||||
num = 0;
|
||||
OPENSSL_FALLTHROUGH;
|
||||
case BIO_C_FILE_SEEK:
|
||||
ret = (long)fseek(fp, num, 0);
|
||||
break;
|
||||
case BIO_CTRL_EOF:
|
||||
ret = (long)feof(fp);
|
||||
break;
|
||||
case BIO_C_FILE_TELL:
|
||||
case BIO_CTRL_INFO:
|
||||
ret = ftell(fp);
|
||||
break;
|
||||
case BIO_C_SET_FILE_PTR:
|
||||
file_free(b);
|
||||
b->shutdown = (int)num & BIO_CLOSE;
|
||||
b->ptr = ptr;
|
||||
b->init = 1;
|
||||
break;
|
||||
case BIO_C_SET_FILENAME:
|
||||
file_free(b);
|
||||
b->shutdown = (int)num & BIO_CLOSE;
|
||||
if (num & BIO_FP_APPEND) {
|
||||
if (num & BIO_FP_READ) {
|
||||
OPENSSL_strlcpy(p, "a+", sizeof(p));
|
||||
} else {
|
||||
OPENSSL_strlcpy(p, "a", sizeof(p));
|
||||
}
|
||||
} else if ((num & BIO_FP_READ) && (num & BIO_FP_WRITE)) {
|
||||
OPENSSL_strlcpy(p, "r+", sizeof(p));
|
||||
} else if (num & BIO_FP_WRITE) {
|
||||
OPENSSL_strlcpy(p, "w", sizeof(p));
|
||||
} else if (num & BIO_FP_READ) {
|
||||
OPENSSL_strlcpy(p, "r", sizeof(p));
|
||||
} else {
|
||||
OPENSSL_PUT_ERROR(BIO, BIO_R_BAD_FOPEN_MODE);
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
fp = fopen(ptr, p);
|
||||
if (fp == NULL) {
|
||||
OPENSSL_PUT_SYSTEM_ERROR();
|
||||
ERR_add_error_data(5, "fopen('", ptr, "','", p, "')");
|
||||
OPENSSL_PUT_ERROR(BIO, ERR_R_SYS_LIB);
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
b->ptr = fp;
|
||||
b->init = 1;
|
||||
break;
|
||||
case BIO_C_GET_FILE_PTR:
|
||||
// the ptr parameter is actually a FILE ** in this case.
|
||||
if (ptr != NULL) {
|
||||
fpp = (FILE **)ptr;
|
||||
*fpp = (FILE *)b->ptr;
|
||||
}
|
||||
break;
|
||||
case BIO_CTRL_GET_CLOSE:
|
||||
ret = (long)b->shutdown;
|
||||
break;
|
||||
case BIO_CTRL_SET_CLOSE:
|
||||
b->shutdown = (int)num;
|
||||
break;
|
||||
case BIO_CTRL_FLUSH:
|
||||
ret = 0 == fflush((FILE *)b->ptr);
|
||||
break;
|
||||
case BIO_CTRL_WPENDING:
|
||||
case BIO_CTRL_PENDING:
|
||||
default:
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int file_gets(BIO *bp, char *buf, int size) {
|
||||
int ret = 0;
|
||||
|
||||
if (size == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!fgets(buf, size, (FILE *)bp->ptr)) {
|
||||
buf[0] = 0;
|
||||
goto err;
|
||||
}
|
||||
ret = strlen(buf);
|
||||
|
||||
err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const BIO_METHOD methods_filep = {
|
||||
BIO_TYPE_FILE, "FILE pointer",
|
||||
file_write, file_read,
|
||||
NULL /* puts */, file_gets,
|
||||
file_ctrl, file_new,
|
||||
file_free, NULL /* callback_ctrl */,
|
||||
};
|
||||
|
||||
const BIO_METHOD *BIO_s_file(void) { return &methods_filep; }
|
||||
|
||||
|
||||
int BIO_get_fp(BIO *bio, FILE **out_file) {
|
||||
return BIO_ctrl(bio, BIO_C_GET_FILE_PTR, 0, (char*) out_file);
|
||||
}
|
||||
|
||||
int BIO_set_fp(BIO *bio, FILE *file, int close_flag) {
|
||||
return BIO_ctrl(bio, BIO_C_SET_FILE_PTR, close_flag, (char *) file);
|
||||
}
|
||||
|
||||
int BIO_read_filename(BIO *bio, const char *filename) {
|
||||
return BIO_ctrl(bio, BIO_C_SET_FILENAME, BIO_CLOSE | BIO_FP_READ,
|
||||
(char *)filename);
|
||||
}
|
||||
|
||||
int BIO_write_filename(BIO *bio, const char *filename) {
|
||||
return BIO_ctrl(bio, BIO_C_SET_FILENAME, BIO_CLOSE | BIO_FP_WRITE,
|
||||
(char *)filename);
|
||||
}
|
||||
|
||||
int BIO_append_filename(BIO *bio, const char *filename) {
|
||||
return BIO_ctrl(bio, BIO_C_SET_FILENAME, BIO_CLOSE | BIO_FP_APPEND,
|
||||
(char *)filename);
|
||||
}
|
||||
|
||||
int BIO_rw_filename(BIO *bio, const char *filename) {
|
||||
return BIO_ctrl(bio, BIO_C_SET_FILENAME,
|
||||
BIO_CLOSE | BIO_FP_READ | BIO_FP_WRITE, (char *)filename);
|
||||
}
|
||||
|
||||
#endif // OPENSSL_TRUSTY
|
||||
+192
@@ -0,0 +1,192 @@
|
||||
/* Copyright (C) 1995-1998 Eric Young ([email protected])
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young ([email protected]).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson ([email protected]).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young ([email protected])"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson ([email protected])"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.] */
|
||||
|
||||
#include <openssl_grpc/bio.h>
|
||||
|
||||
#include <limits.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "../internal.h"
|
||||
|
||||
|
||||
// hexdump_ctx contains the state of a hexdump.
|
||||
struct hexdump_ctx {
|
||||
BIO *bio;
|
||||
char right_chars[18]; // the contents of the right-hand side, ASCII dump.
|
||||
unsigned used; // number of bytes in the current line.
|
||||
size_t n; // number of bytes total.
|
||||
unsigned indent;
|
||||
};
|
||||
|
||||
static void hexbyte(char *out, uint8_t b) {
|
||||
static const char hextable[] = "0123456789abcdef";
|
||||
out[0] = hextable[b>>4];
|
||||
out[1] = hextable[b&0x0f];
|
||||
}
|
||||
|
||||
static char to_char(uint8_t b) {
|
||||
if (b < 32 || b > 126) {
|
||||
return '.';
|
||||
}
|
||||
return b;
|
||||
}
|
||||
|
||||
// hexdump_write adds |len| bytes of |data| to the current hex dump described by
|
||||
// |ctx|.
|
||||
static int hexdump_write(struct hexdump_ctx *ctx, const uint8_t *data,
|
||||
size_t len) {
|
||||
char buf[10];
|
||||
unsigned l;
|
||||
|
||||
// Output lines look like:
|
||||
// 00000010 2e 2f 30 31 32 33 34 35 36 37 38 ... 3c 3d // |./0123456789:;<=|
|
||||
// ^ offset ^ extra space ^ ASCII of line
|
||||
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
if (ctx->used == 0) {
|
||||
// The beginning of a line.
|
||||
BIO_indent(ctx->bio, ctx->indent, UINT_MAX);
|
||||
|
||||
hexbyte(&buf[0], ctx->n >> 24);
|
||||
hexbyte(&buf[2], ctx->n >> 16);
|
||||
hexbyte(&buf[4], ctx->n >> 8);
|
||||
hexbyte(&buf[6], ctx->n);
|
||||
buf[8] = buf[9] = ' ';
|
||||
if (BIO_write(ctx->bio, buf, 10) < 0) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
hexbyte(buf, data[i]);
|
||||
buf[2] = ' ';
|
||||
l = 3;
|
||||
if (ctx->used == 7) {
|
||||
// There's an additional space after the 8th byte.
|
||||
buf[3] = ' ';
|
||||
l = 4;
|
||||
} else if (ctx->used == 15) {
|
||||
// At the end of the line there's an extra space and the bar for the
|
||||
// right column.
|
||||
buf[3] = ' ';
|
||||
buf[4] = '|';
|
||||
l = 5;
|
||||
}
|
||||
|
||||
if (BIO_write(ctx->bio, buf, l) < 0) {
|
||||
return 0;
|
||||
}
|
||||
ctx->right_chars[ctx->used] = to_char(data[i]);
|
||||
ctx->used++;
|
||||
ctx->n++;
|
||||
if (ctx->used == 16) {
|
||||
ctx->right_chars[16] = '|';
|
||||
ctx->right_chars[17] = '\n';
|
||||
if (BIO_write(ctx->bio, ctx->right_chars, sizeof(ctx->right_chars)) < 0) {
|
||||
return 0;
|
||||
}
|
||||
ctx->used = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
// finish flushes any buffered data in |ctx|.
|
||||
static int finish(struct hexdump_ctx *ctx) {
|
||||
// See the comments in |hexdump| for the details of this format.
|
||||
const unsigned n_bytes = ctx->used;
|
||||
unsigned l;
|
||||
char buf[5];
|
||||
|
||||
if (n_bytes == 0) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
OPENSSL_memset(buf, ' ', 4);
|
||||
buf[4] = '|';
|
||||
|
||||
for (; ctx->used < 16; ctx->used++) {
|
||||
l = 3;
|
||||
if (ctx->used == 7) {
|
||||
l = 4;
|
||||
} else if (ctx->used == 15) {
|
||||
l = 5;
|
||||
}
|
||||
if (BIO_write(ctx->bio, buf, l) < 0) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
ctx->right_chars[n_bytes] = '|';
|
||||
ctx->right_chars[n_bytes + 1] = '\n';
|
||||
if (BIO_write(ctx->bio, ctx->right_chars, n_bytes + 2) < 0) {
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int BIO_hexdump(BIO *bio, const uint8_t *data, size_t len, unsigned indent) {
|
||||
struct hexdump_ctx ctx;
|
||||
OPENSSL_memset(&ctx, 0, sizeof(ctx));
|
||||
ctx.bio = bio;
|
||||
ctx.indent = indent;
|
||||
|
||||
if (!hexdump_write(&ctx, data, len) || !finish(&ctx)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
+192
@@ -0,0 +1,192 @@
|
||||
/* Copyright (C) 1995-1998 Eric Young ([email protected])
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young ([email protected]).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson ([email protected]).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young ([email protected])"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson ([email protected])"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.] */
|
||||
|
||||
#include <openssl/bio.h>
|
||||
|
||||
#include <limits.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "../internal.h"
|
||||
|
||||
|
||||
// hexdump_ctx contains the state of a hexdump.
|
||||
struct hexdump_ctx {
|
||||
BIO *bio;
|
||||
char right_chars[18]; // the contents of the right-hand side, ASCII dump.
|
||||
unsigned used; // number of bytes in the current line.
|
||||
size_t n; // number of bytes total.
|
||||
unsigned indent;
|
||||
};
|
||||
|
||||
static void hexbyte(char *out, uint8_t b) {
|
||||
static const char hextable[] = "0123456789abcdef";
|
||||
out[0] = hextable[b>>4];
|
||||
out[1] = hextable[b&0x0f];
|
||||
}
|
||||
|
||||
static char to_char(uint8_t b) {
|
||||
if (b < 32 || b > 126) {
|
||||
return '.';
|
||||
}
|
||||
return b;
|
||||
}
|
||||
|
||||
// hexdump_write adds |len| bytes of |data| to the current hex dump described by
|
||||
// |ctx|.
|
||||
static int hexdump_write(struct hexdump_ctx *ctx, const uint8_t *data,
|
||||
size_t len) {
|
||||
char buf[10];
|
||||
unsigned l;
|
||||
|
||||
// Output lines look like:
|
||||
// 00000010 2e 2f 30 31 32 33 34 35 36 37 38 ... 3c 3d // |./0123456789:;<=|
|
||||
// ^ offset ^ extra space ^ ASCII of line
|
||||
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
if (ctx->used == 0) {
|
||||
// The beginning of a line.
|
||||
BIO_indent(ctx->bio, ctx->indent, UINT_MAX);
|
||||
|
||||
hexbyte(&buf[0], ctx->n >> 24);
|
||||
hexbyte(&buf[2], ctx->n >> 16);
|
||||
hexbyte(&buf[4], ctx->n >> 8);
|
||||
hexbyte(&buf[6], ctx->n);
|
||||
buf[8] = buf[9] = ' ';
|
||||
if (BIO_write(ctx->bio, buf, 10) < 0) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
hexbyte(buf, data[i]);
|
||||
buf[2] = ' ';
|
||||
l = 3;
|
||||
if (ctx->used == 7) {
|
||||
// There's an additional space after the 8th byte.
|
||||
buf[3] = ' ';
|
||||
l = 4;
|
||||
} else if (ctx->used == 15) {
|
||||
// At the end of the line there's an extra space and the bar for the
|
||||
// right column.
|
||||
buf[3] = ' ';
|
||||
buf[4] = '|';
|
||||
l = 5;
|
||||
}
|
||||
|
||||
if (BIO_write(ctx->bio, buf, l) < 0) {
|
||||
return 0;
|
||||
}
|
||||
ctx->right_chars[ctx->used] = to_char(data[i]);
|
||||
ctx->used++;
|
||||
ctx->n++;
|
||||
if (ctx->used == 16) {
|
||||
ctx->right_chars[16] = '|';
|
||||
ctx->right_chars[17] = '\n';
|
||||
if (BIO_write(ctx->bio, ctx->right_chars, sizeof(ctx->right_chars)) < 0) {
|
||||
return 0;
|
||||
}
|
||||
ctx->used = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
// finish flushes any buffered data in |ctx|.
|
||||
static int finish(struct hexdump_ctx *ctx) {
|
||||
// See the comments in |hexdump| for the details of this format.
|
||||
const unsigned n_bytes = ctx->used;
|
||||
unsigned l;
|
||||
char buf[5];
|
||||
|
||||
if (n_bytes == 0) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
OPENSSL_memset(buf, ' ', 4);
|
||||
buf[4] = '|';
|
||||
|
||||
for (; ctx->used < 16; ctx->used++) {
|
||||
l = 3;
|
||||
if (ctx->used == 7) {
|
||||
l = 4;
|
||||
} else if (ctx->used == 15) {
|
||||
l = 5;
|
||||
}
|
||||
if (BIO_write(ctx->bio, buf, l) < 0) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
ctx->right_chars[n_bytes] = '|';
|
||||
ctx->right_chars[n_bytes + 1] = '\n';
|
||||
if (BIO_write(ctx->bio, ctx->right_chars, n_bytes + 2) < 0) {
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int BIO_hexdump(BIO *bio, const uint8_t *data, size_t len, unsigned indent) {
|
||||
struct hexdump_ctx ctx;
|
||||
OPENSSL_memset(&ctx, 0, sizeof(ctx));
|
||||
ctx.bio = bio;
|
||||
ctx.indent = indent;
|
||||
|
||||
if (!hexdump_write(&ctx, data, len) || !finish(&ctx)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
+111
@@ -0,0 +1,111 @@
|
||||
/* Copyright (C) 1995-1998 Eric Young ([email protected])
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young ([email protected]).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson ([email protected]).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young ([email protected])"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson ([email protected])"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.] */
|
||||
|
||||
#ifndef OPENSSL_HEADER_BIO_INTERNAL_H
|
||||
#define OPENSSL_HEADER_BIO_INTERNAL_H
|
||||
|
||||
#include <openssl_grpc/base.h>
|
||||
|
||||
#if !defined(OPENSSL_WINDOWS)
|
||||
#if defined(OPENSSL_PNACL)
|
||||
// newlib uses u_short in socket.h without defining it.
|
||||
typedef unsigned short u_short;
|
||||
#endif
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#else
|
||||
OPENSSL_MSVC_PRAGMA(warning(push, 3))
|
||||
#include <winsock2.h>
|
||||
OPENSSL_MSVC_PRAGMA(warning(pop))
|
||||
typedef int socklen_t;
|
||||
#endif
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
// BIO_ip_and_port_to_socket_and_addr creates a socket and fills in |*out_addr|
|
||||
// and |*out_addr_length| with the correct values for connecting to |hostname|
|
||||
// on |port_str|. It returns one on success or zero on error.
|
||||
int bio_ip_and_port_to_socket_and_addr(int *out_sock,
|
||||
struct sockaddr_storage *out_addr,
|
||||
socklen_t *out_addr_length,
|
||||
const char *hostname,
|
||||
const char *port_str);
|
||||
|
||||
// BIO_socket_nbio sets whether |sock| is non-blocking. It returns one on
|
||||
// success and zero otherwise.
|
||||
int bio_socket_nbio(int sock, int on);
|
||||
|
||||
// BIO_clear_socket_error clears the last system socket error.
|
||||
//
|
||||
// TODO(fork): remove all callers of this.
|
||||
void bio_clear_socket_error(void);
|
||||
|
||||
// BIO_sock_error returns the last socket error on |sock|.
|
||||
int bio_sock_error(int sock);
|
||||
|
||||
// BIO_fd_should_retry returns non-zero if |return_value| indicates an error
|
||||
// and |errno| indicates that it's non-fatal.
|
||||
int bio_fd_should_retry(int return_value);
|
||||
|
||||
|
||||
#if defined(__cplusplus)
|
||||
} // extern C
|
||||
#endif
|
||||
|
||||
#endif // OPENSSL_HEADER_BIO_INTERNAL_H
|
||||
+111
@@ -0,0 +1,111 @@
|
||||
/* Copyright (C) 1995-1998 Eric Young ([email protected])
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young ([email protected]).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson ([email protected]).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young ([email protected])"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson ([email protected])"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.] */
|
||||
|
||||
#ifndef OPENSSL_HEADER_BIO_INTERNAL_H
|
||||
#define OPENSSL_HEADER_BIO_INTERNAL_H
|
||||
|
||||
#include <openssl/base.h>
|
||||
|
||||
#if !defined(OPENSSL_WINDOWS)
|
||||
#if defined(OPENSSL_PNACL)
|
||||
// newlib uses u_short in socket.h without defining it.
|
||||
typedef unsigned short u_short;
|
||||
#endif
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#else
|
||||
OPENSSL_MSVC_PRAGMA(warning(push, 3))
|
||||
#include <winsock2.h>
|
||||
OPENSSL_MSVC_PRAGMA(warning(pop))
|
||||
typedef int socklen_t;
|
||||
#endif
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
// BIO_ip_and_port_to_socket_and_addr creates a socket and fills in |*out_addr|
|
||||
// and |*out_addr_length| with the correct values for connecting to |hostname|
|
||||
// on |port_str|. It returns one on success or zero on error.
|
||||
int bio_ip_and_port_to_socket_and_addr(int *out_sock,
|
||||
struct sockaddr_storage *out_addr,
|
||||
socklen_t *out_addr_length,
|
||||
const char *hostname,
|
||||
const char *port_str);
|
||||
|
||||
// BIO_socket_nbio sets whether |sock| is non-blocking. It returns one on
|
||||
// success and zero otherwise.
|
||||
int bio_socket_nbio(int sock, int on);
|
||||
|
||||
// BIO_clear_socket_error clears the last system socket error.
|
||||
//
|
||||
// TODO(fork): remove all callers of this.
|
||||
void bio_clear_socket_error(void);
|
||||
|
||||
// BIO_sock_error returns the last socket error on |sock|.
|
||||
int bio_sock_error(int sock);
|
||||
|
||||
// BIO_fd_should_retry returns non-zero if |return_value| indicates an error
|
||||
// and |errno| indicates that it's non-fatal.
|
||||
int bio_fd_should_retry(int return_value);
|
||||
|
||||
|
||||
#if defined(__cplusplus)
|
||||
} // extern C
|
||||
#endif
|
||||
|
||||
#endif // OPENSSL_HEADER_BIO_INTERNAL_H
|
||||
+488
@@ -0,0 +1,488 @@
|
||||
/* ====================================================================
|
||||
* Copyright (c) 1998-2003 The OpenSSL Project. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* 3. All advertising materials mentioning features or use of this
|
||||
* software must display the following acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
|
||||
*
|
||||
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
|
||||
* endorse or promote products derived from this software without
|
||||
* prior written permission. For written permission, please contact
|
||||
* [email protected].
|
||||
*
|
||||
* 5. Products derived from this software may not be called "OpenSSL"
|
||||
* nor may "OpenSSL" appear in their names without prior written
|
||||
* permission of the OpenSSL Project.
|
||||
*
|
||||
* 6. Redistributions of any form whatsoever must retain the following
|
||||
* acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit (http://www.openssl.org/)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
|
||||
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
|
||||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ====================================================================
|
||||
*
|
||||
* This product includes cryptographic software written by Eric Young
|
||||
* ([email protected]). This product includes software written by Tim
|
||||
* Hudson ([email protected]). */
|
||||
|
||||
#include <openssl_grpc/bio.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <openssl_grpc/err.h>
|
||||
#include <openssl_grpc/mem.h>
|
||||
|
||||
#include "../internal.h"
|
||||
|
||||
|
||||
struct bio_bio_st {
|
||||
BIO *peer; // NULL if buf == NULL.
|
||||
// If peer != NULL, then peer->ptr is also a bio_bio_st,
|
||||
// and its "peer" member points back to us.
|
||||
// peer != NULL iff init != 0 in the BIO.
|
||||
|
||||
// This is for what we write (i.e. reading uses peer's struct):
|
||||
int closed; // valid iff peer != NULL
|
||||
size_t len; // valid iff buf != NULL; 0 if peer == NULL
|
||||
size_t offset; // valid iff buf != NULL; 0 if len == 0
|
||||
size_t size;
|
||||
uint8_t *buf; // "size" elements (if != NULL)
|
||||
|
||||
size_t request; // valid iff peer != NULL; 0 if len != 0,
|
||||
// otherwise set by peer to number of bytes
|
||||
// it (unsuccessfully) tried to read,
|
||||
// never more than buffer space (size-len) warrants.
|
||||
};
|
||||
|
||||
static int bio_new(BIO *bio) {
|
||||
struct bio_bio_st *b;
|
||||
|
||||
b = OPENSSL_malloc(sizeof *b);
|
||||
if (b == NULL) {
|
||||
return 0;
|
||||
}
|
||||
OPENSSL_memset(b, 0, sizeof(struct bio_bio_st));
|
||||
|
||||
b->size = 17 * 1024; // enough for one TLS record (just a default)
|
||||
bio->ptr = b;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void bio_destroy_pair(BIO *bio) {
|
||||
struct bio_bio_st *b = bio->ptr;
|
||||
BIO *peer_bio;
|
||||
struct bio_bio_st *peer_b;
|
||||
|
||||
if (b == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
peer_bio = b->peer;
|
||||
if (peer_bio == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
peer_b = peer_bio->ptr;
|
||||
|
||||
assert(peer_b != NULL);
|
||||
assert(peer_b->peer == bio);
|
||||
|
||||
peer_b->peer = NULL;
|
||||
peer_bio->init = 0;
|
||||
assert(peer_b->buf != NULL);
|
||||
peer_b->len = 0;
|
||||
peer_b->offset = 0;
|
||||
|
||||
b->peer = NULL;
|
||||
bio->init = 0;
|
||||
assert(b->buf != NULL);
|
||||
b->len = 0;
|
||||
b->offset = 0;
|
||||
}
|
||||
|
||||
static int bio_free(BIO *bio) {
|
||||
struct bio_bio_st *b;
|
||||
|
||||
if (bio == NULL) {
|
||||
return 0;
|
||||
}
|
||||
b = bio->ptr;
|
||||
|
||||
assert(b != NULL);
|
||||
|
||||
if (b->peer) {
|
||||
bio_destroy_pair(bio);
|
||||
}
|
||||
|
||||
OPENSSL_free(b->buf);
|
||||
OPENSSL_free(b);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int bio_read(BIO *bio, char *buf, int size_) {
|
||||
size_t size = size_;
|
||||
size_t rest;
|
||||
struct bio_bio_st *b, *peer_b;
|
||||
|
||||
BIO_clear_retry_flags(bio);
|
||||
|
||||
if (!bio->init) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
b = bio->ptr;
|
||||
assert(b != NULL);
|
||||
assert(b->peer != NULL);
|
||||
peer_b = b->peer->ptr;
|
||||
assert(peer_b != NULL);
|
||||
assert(peer_b->buf != NULL);
|
||||
|
||||
peer_b->request = 0; // will be set in "retry_read" situation
|
||||
|
||||
if (buf == NULL || size == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (peer_b->len == 0) {
|
||||
if (peer_b->closed) {
|
||||
return 0; // writer has closed, and no data is left
|
||||
} else {
|
||||
BIO_set_retry_read(bio); // buffer is empty
|
||||
if (size <= peer_b->size) {
|
||||
peer_b->request = size;
|
||||
} else {
|
||||
// don't ask for more than the peer can
|
||||
// deliver in one write
|
||||
peer_b->request = peer_b->size;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
// we can read
|
||||
if (peer_b->len < size) {
|
||||
size = peer_b->len;
|
||||
}
|
||||
|
||||
// now read "size" bytes
|
||||
rest = size;
|
||||
|
||||
assert(rest > 0);
|
||||
// one or two iterations
|
||||
do {
|
||||
size_t chunk;
|
||||
|
||||
assert(rest <= peer_b->len);
|
||||
if (peer_b->offset + rest <= peer_b->size) {
|
||||
chunk = rest;
|
||||
} else {
|
||||
// wrap around ring buffer
|
||||
chunk = peer_b->size - peer_b->offset;
|
||||
}
|
||||
assert(peer_b->offset + chunk <= peer_b->size);
|
||||
|
||||
OPENSSL_memcpy(buf, peer_b->buf + peer_b->offset, chunk);
|
||||
|
||||
peer_b->len -= chunk;
|
||||
if (peer_b->len) {
|
||||
peer_b->offset += chunk;
|
||||
assert(peer_b->offset <= peer_b->size);
|
||||
if (peer_b->offset == peer_b->size) {
|
||||
peer_b->offset = 0;
|
||||
}
|
||||
buf += chunk;
|
||||
} else {
|
||||
// buffer now empty, no need to advance "buf"
|
||||
assert(chunk == rest);
|
||||
peer_b->offset = 0;
|
||||
}
|
||||
rest -= chunk;
|
||||
} while (rest);
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static int bio_write(BIO *bio, const char *buf, int num_) {
|
||||
size_t num = num_;
|
||||
size_t rest;
|
||||
struct bio_bio_st *b;
|
||||
|
||||
BIO_clear_retry_flags(bio);
|
||||
|
||||
if (!bio->init || buf == NULL || num == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
b = bio->ptr;
|
||||
assert(b != NULL);
|
||||
assert(b->peer != NULL);
|
||||
assert(b->buf != NULL);
|
||||
|
||||
b->request = 0;
|
||||
if (b->closed) {
|
||||
// we already closed
|
||||
OPENSSL_PUT_ERROR(BIO, BIO_R_BROKEN_PIPE);
|
||||
return -1;
|
||||
}
|
||||
|
||||
assert(b->len <= b->size);
|
||||
|
||||
if (b->len == b->size) {
|
||||
BIO_set_retry_write(bio); // buffer is full
|
||||
return -1;
|
||||
}
|
||||
|
||||
// we can write
|
||||
if (num > b->size - b->len) {
|
||||
num = b->size - b->len;
|
||||
}
|
||||
|
||||
// now write "num" bytes
|
||||
rest = num;
|
||||
|
||||
assert(rest > 0);
|
||||
// one or two iterations
|
||||
do {
|
||||
size_t write_offset;
|
||||
size_t chunk;
|
||||
|
||||
assert(b->len + rest <= b->size);
|
||||
|
||||
write_offset = b->offset + b->len;
|
||||
if (write_offset >= b->size) {
|
||||
write_offset -= b->size;
|
||||
}
|
||||
// b->buf[write_offset] is the first byte we can write to.
|
||||
|
||||
if (write_offset + rest <= b->size) {
|
||||
chunk = rest;
|
||||
} else {
|
||||
// wrap around ring buffer
|
||||
chunk = b->size - write_offset;
|
||||
}
|
||||
|
||||
OPENSSL_memcpy(b->buf + write_offset, buf, chunk);
|
||||
|
||||
b->len += chunk;
|
||||
|
||||
assert(b->len <= b->size);
|
||||
|
||||
rest -= chunk;
|
||||
buf += chunk;
|
||||
} while (rest);
|
||||
|
||||
return num;
|
||||
}
|
||||
|
||||
static int bio_make_pair(BIO *bio1, BIO *bio2, size_t writebuf1_len,
|
||||
size_t writebuf2_len) {
|
||||
struct bio_bio_st *b1, *b2;
|
||||
|
||||
assert(bio1 != NULL);
|
||||
assert(bio2 != NULL);
|
||||
|
||||
b1 = bio1->ptr;
|
||||
b2 = bio2->ptr;
|
||||
|
||||
if (b1->peer != NULL || b2->peer != NULL) {
|
||||
OPENSSL_PUT_ERROR(BIO, BIO_R_IN_USE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (b1->buf == NULL) {
|
||||
if (writebuf1_len) {
|
||||
b1->size = writebuf1_len;
|
||||
}
|
||||
b1->buf = OPENSSL_malloc(b1->size);
|
||||
if (b1->buf == NULL) {
|
||||
OPENSSL_PUT_ERROR(BIO, ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
b1->len = 0;
|
||||
b1->offset = 0;
|
||||
}
|
||||
|
||||
if (b2->buf == NULL) {
|
||||
if (writebuf2_len) {
|
||||
b2->size = writebuf2_len;
|
||||
}
|
||||
b2->buf = OPENSSL_malloc(b2->size);
|
||||
if (b2->buf == NULL) {
|
||||
OPENSSL_PUT_ERROR(BIO, ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
b2->len = 0;
|
||||
b2->offset = 0;
|
||||
}
|
||||
|
||||
b1->peer = bio2;
|
||||
b1->closed = 0;
|
||||
b1->request = 0;
|
||||
b2->peer = bio1;
|
||||
b2->closed = 0;
|
||||
b2->request = 0;
|
||||
|
||||
bio1->init = 1;
|
||||
bio2->init = 1;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static long bio_ctrl(BIO *bio, int cmd, long num, void *ptr) {
|
||||
long ret;
|
||||
struct bio_bio_st *b = bio->ptr;
|
||||
|
||||
assert(b != NULL);
|
||||
|
||||
switch (cmd) {
|
||||
// specific CTRL codes
|
||||
|
||||
case BIO_C_GET_WRITE_BUF_SIZE:
|
||||
ret = (long)b->size;
|
||||
break;
|
||||
|
||||
case BIO_C_GET_WRITE_GUARANTEE:
|
||||
// How many bytes can the caller feed to the next write
|
||||
// without having to keep any?
|
||||
if (b->peer == NULL || b->closed) {
|
||||
ret = 0;
|
||||
} else {
|
||||
ret = (long)b->size - b->len;
|
||||
}
|
||||
break;
|
||||
|
||||
case BIO_C_GET_READ_REQUEST:
|
||||
// If the peer unsuccessfully tried to read, how many bytes
|
||||
// were requested? (As with BIO_CTRL_PENDING, that number
|
||||
// can usually be treated as boolean.)
|
||||
ret = (long)b->request;
|
||||
break;
|
||||
|
||||
case BIO_C_RESET_READ_REQUEST:
|
||||
// Reset request. (Can be useful after read attempts
|
||||
// at the other side that are meant to be non-blocking,
|
||||
// e.g. when probing SSL_read to see if any data is
|
||||
// available.)
|
||||
b->request = 0;
|
||||
ret = 1;
|
||||
break;
|
||||
|
||||
case BIO_C_SHUTDOWN_WR:
|
||||
// similar to shutdown(..., SHUT_WR)
|
||||
b->closed = 1;
|
||||
ret = 1;
|
||||
break;
|
||||
|
||||
// standard CTRL codes follow
|
||||
|
||||
case BIO_CTRL_GET_CLOSE:
|
||||
ret = bio->shutdown;
|
||||
break;
|
||||
|
||||
case BIO_CTRL_SET_CLOSE:
|
||||
bio->shutdown = (int)num;
|
||||
ret = 1;
|
||||
break;
|
||||
|
||||
case BIO_CTRL_PENDING:
|
||||
if (b->peer != NULL) {
|
||||
struct bio_bio_st *peer_b = b->peer->ptr;
|
||||
ret = (long)peer_b->len;
|
||||
} else {
|
||||
ret = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case BIO_CTRL_WPENDING:
|
||||
ret = 0;
|
||||
if (b->buf != NULL) {
|
||||
ret = (long)b->len;
|
||||
}
|
||||
break;
|
||||
|
||||
case BIO_CTRL_FLUSH:
|
||||
ret = 1;
|
||||
break;
|
||||
|
||||
case BIO_CTRL_EOF: {
|
||||
BIO *other_bio = ptr;
|
||||
|
||||
if (other_bio) {
|
||||
struct bio_bio_st *other_b = other_bio->ptr;
|
||||
assert(other_b != NULL);
|
||||
ret = other_b->len == 0 && other_b->closed;
|
||||
} else {
|
||||
ret = 1;
|
||||
}
|
||||
} break;
|
||||
|
||||
default:
|
||||
ret = 0;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static const BIO_METHOD methods_biop = {
|
||||
BIO_TYPE_BIO, "BIO pair", bio_write, bio_read, NULL /* puts */,
|
||||
NULL /* gets */, bio_ctrl, bio_new, bio_free, NULL /* callback_ctrl */,
|
||||
};
|
||||
|
||||
static const BIO_METHOD *bio_s_bio(void) { return &methods_biop; }
|
||||
|
||||
int BIO_new_bio_pair(BIO** bio1_p, size_t writebuf1_len,
|
||||
BIO** bio2_p, size_t writebuf2_len) {
|
||||
BIO *bio1 = BIO_new(bio_s_bio());
|
||||
BIO *bio2 = BIO_new(bio_s_bio());
|
||||
if (bio1 == NULL || bio2 == NULL ||
|
||||
!bio_make_pair(bio1, bio2, writebuf1_len, writebuf2_len)) {
|
||||
BIO_free(bio1);
|
||||
BIO_free(bio2);
|
||||
*bio1_p = NULL;
|
||||
*bio2_p = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
*bio1_p = bio1;
|
||||
*bio2_p = bio2;
|
||||
return 1;
|
||||
}
|
||||
|
||||
size_t BIO_ctrl_get_read_request(BIO *bio) {
|
||||
return BIO_ctrl(bio, BIO_C_GET_READ_REQUEST, 0, NULL);
|
||||
}
|
||||
|
||||
size_t BIO_ctrl_get_write_guarantee(BIO *bio) {
|
||||
return BIO_ctrl(bio, BIO_C_GET_WRITE_GUARANTEE, 0, NULL);
|
||||
}
|
||||
|
||||
int BIO_shutdown_wr(BIO *bio) {
|
||||
return BIO_ctrl(bio, BIO_C_SHUTDOWN_WR, 0, NULL);
|
||||
}
|
||||
+488
@@ -0,0 +1,488 @@
|
||||
/* ====================================================================
|
||||
* Copyright (c) 1998-2003 The OpenSSL Project. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* 3. All advertising materials mentioning features or use of this
|
||||
* software must display the following acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
|
||||
*
|
||||
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
|
||||
* endorse or promote products derived from this software without
|
||||
* prior written permission. For written permission, please contact
|
||||
* [email protected].
|
||||
*
|
||||
* 5. Products derived from this software may not be called "OpenSSL"
|
||||
* nor may "OpenSSL" appear in their names without prior written
|
||||
* permission of the OpenSSL Project.
|
||||
*
|
||||
* 6. Redistributions of any form whatsoever must retain the following
|
||||
* acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit (http://www.openssl.org/)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
|
||||
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
|
||||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ====================================================================
|
||||
*
|
||||
* This product includes cryptographic software written by Eric Young
|
||||
* ([email protected]). This product includes software written by Tim
|
||||
* Hudson ([email protected]). */
|
||||
|
||||
#include <openssl/bio.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/mem.h>
|
||||
|
||||
#include "../internal.h"
|
||||
|
||||
|
||||
struct bio_bio_st {
|
||||
BIO *peer; // NULL if buf == NULL.
|
||||
// If peer != NULL, then peer->ptr is also a bio_bio_st,
|
||||
// and its "peer" member points back to us.
|
||||
// peer != NULL iff init != 0 in the BIO.
|
||||
|
||||
// This is for what we write (i.e. reading uses peer's struct):
|
||||
int closed; // valid iff peer != NULL
|
||||
size_t len; // valid iff buf != NULL; 0 if peer == NULL
|
||||
size_t offset; // valid iff buf != NULL; 0 if len == 0
|
||||
size_t size;
|
||||
uint8_t *buf; // "size" elements (if != NULL)
|
||||
|
||||
size_t request; // valid iff peer != NULL; 0 if len != 0,
|
||||
// otherwise set by peer to number of bytes
|
||||
// it (unsuccessfully) tried to read,
|
||||
// never more than buffer space (size-len) warrants.
|
||||
};
|
||||
|
||||
static int bio_new(BIO *bio) {
|
||||
struct bio_bio_st *b;
|
||||
|
||||
b = OPENSSL_malloc(sizeof *b);
|
||||
if (b == NULL) {
|
||||
return 0;
|
||||
}
|
||||
OPENSSL_memset(b, 0, sizeof(struct bio_bio_st));
|
||||
|
||||
b->size = 17 * 1024; // enough for one TLS record (just a default)
|
||||
bio->ptr = b;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void bio_destroy_pair(BIO *bio) {
|
||||
struct bio_bio_st *b = bio->ptr;
|
||||
BIO *peer_bio;
|
||||
struct bio_bio_st *peer_b;
|
||||
|
||||
if (b == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
peer_bio = b->peer;
|
||||
if (peer_bio == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
peer_b = peer_bio->ptr;
|
||||
|
||||
assert(peer_b != NULL);
|
||||
assert(peer_b->peer == bio);
|
||||
|
||||
peer_b->peer = NULL;
|
||||
peer_bio->init = 0;
|
||||
assert(peer_b->buf != NULL);
|
||||
peer_b->len = 0;
|
||||
peer_b->offset = 0;
|
||||
|
||||
b->peer = NULL;
|
||||
bio->init = 0;
|
||||
assert(b->buf != NULL);
|
||||
b->len = 0;
|
||||
b->offset = 0;
|
||||
}
|
||||
|
||||
static int bio_free(BIO *bio) {
|
||||
struct bio_bio_st *b;
|
||||
|
||||
if (bio == NULL) {
|
||||
return 0;
|
||||
}
|
||||
b = bio->ptr;
|
||||
|
||||
assert(b != NULL);
|
||||
|
||||
if (b->peer) {
|
||||
bio_destroy_pair(bio);
|
||||
}
|
||||
|
||||
OPENSSL_free(b->buf);
|
||||
OPENSSL_free(b);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int bio_read(BIO *bio, char *buf, int size_) {
|
||||
size_t size = size_;
|
||||
size_t rest;
|
||||
struct bio_bio_st *b, *peer_b;
|
||||
|
||||
BIO_clear_retry_flags(bio);
|
||||
|
||||
if (!bio->init) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
b = bio->ptr;
|
||||
assert(b != NULL);
|
||||
assert(b->peer != NULL);
|
||||
peer_b = b->peer->ptr;
|
||||
assert(peer_b != NULL);
|
||||
assert(peer_b->buf != NULL);
|
||||
|
||||
peer_b->request = 0; // will be set in "retry_read" situation
|
||||
|
||||
if (buf == NULL || size == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (peer_b->len == 0) {
|
||||
if (peer_b->closed) {
|
||||
return 0; // writer has closed, and no data is left
|
||||
} else {
|
||||
BIO_set_retry_read(bio); // buffer is empty
|
||||
if (size <= peer_b->size) {
|
||||
peer_b->request = size;
|
||||
} else {
|
||||
// don't ask for more than the peer can
|
||||
// deliver in one write
|
||||
peer_b->request = peer_b->size;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
// we can read
|
||||
if (peer_b->len < size) {
|
||||
size = peer_b->len;
|
||||
}
|
||||
|
||||
// now read "size" bytes
|
||||
rest = size;
|
||||
|
||||
assert(rest > 0);
|
||||
// one or two iterations
|
||||
do {
|
||||
size_t chunk;
|
||||
|
||||
assert(rest <= peer_b->len);
|
||||
if (peer_b->offset + rest <= peer_b->size) {
|
||||
chunk = rest;
|
||||
} else {
|
||||
// wrap around ring buffer
|
||||
chunk = peer_b->size - peer_b->offset;
|
||||
}
|
||||
assert(peer_b->offset + chunk <= peer_b->size);
|
||||
|
||||
OPENSSL_memcpy(buf, peer_b->buf + peer_b->offset, chunk);
|
||||
|
||||
peer_b->len -= chunk;
|
||||
if (peer_b->len) {
|
||||
peer_b->offset += chunk;
|
||||
assert(peer_b->offset <= peer_b->size);
|
||||
if (peer_b->offset == peer_b->size) {
|
||||
peer_b->offset = 0;
|
||||
}
|
||||
buf += chunk;
|
||||
} else {
|
||||
// buffer now empty, no need to advance "buf"
|
||||
assert(chunk == rest);
|
||||
peer_b->offset = 0;
|
||||
}
|
||||
rest -= chunk;
|
||||
} while (rest);
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static int bio_write(BIO *bio, const char *buf, int num_) {
|
||||
size_t num = num_;
|
||||
size_t rest;
|
||||
struct bio_bio_st *b;
|
||||
|
||||
BIO_clear_retry_flags(bio);
|
||||
|
||||
if (!bio->init || buf == NULL || num == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
b = bio->ptr;
|
||||
assert(b != NULL);
|
||||
assert(b->peer != NULL);
|
||||
assert(b->buf != NULL);
|
||||
|
||||
b->request = 0;
|
||||
if (b->closed) {
|
||||
// we already closed
|
||||
OPENSSL_PUT_ERROR(BIO, BIO_R_BROKEN_PIPE);
|
||||
return -1;
|
||||
}
|
||||
|
||||
assert(b->len <= b->size);
|
||||
|
||||
if (b->len == b->size) {
|
||||
BIO_set_retry_write(bio); // buffer is full
|
||||
return -1;
|
||||
}
|
||||
|
||||
// we can write
|
||||
if (num > b->size - b->len) {
|
||||
num = b->size - b->len;
|
||||
}
|
||||
|
||||
// now write "num" bytes
|
||||
rest = num;
|
||||
|
||||
assert(rest > 0);
|
||||
// one or two iterations
|
||||
do {
|
||||
size_t write_offset;
|
||||
size_t chunk;
|
||||
|
||||
assert(b->len + rest <= b->size);
|
||||
|
||||
write_offset = b->offset + b->len;
|
||||
if (write_offset >= b->size) {
|
||||
write_offset -= b->size;
|
||||
}
|
||||
// b->buf[write_offset] is the first byte we can write to.
|
||||
|
||||
if (write_offset + rest <= b->size) {
|
||||
chunk = rest;
|
||||
} else {
|
||||
// wrap around ring buffer
|
||||
chunk = b->size - write_offset;
|
||||
}
|
||||
|
||||
OPENSSL_memcpy(b->buf + write_offset, buf, chunk);
|
||||
|
||||
b->len += chunk;
|
||||
|
||||
assert(b->len <= b->size);
|
||||
|
||||
rest -= chunk;
|
||||
buf += chunk;
|
||||
} while (rest);
|
||||
|
||||
return num;
|
||||
}
|
||||
|
||||
static int bio_make_pair(BIO *bio1, BIO *bio2, size_t writebuf1_len,
|
||||
size_t writebuf2_len) {
|
||||
struct bio_bio_st *b1, *b2;
|
||||
|
||||
assert(bio1 != NULL);
|
||||
assert(bio2 != NULL);
|
||||
|
||||
b1 = bio1->ptr;
|
||||
b2 = bio2->ptr;
|
||||
|
||||
if (b1->peer != NULL || b2->peer != NULL) {
|
||||
OPENSSL_PUT_ERROR(BIO, BIO_R_IN_USE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (b1->buf == NULL) {
|
||||
if (writebuf1_len) {
|
||||
b1->size = writebuf1_len;
|
||||
}
|
||||
b1->buf = OPENSSL_malloc(b1->size);
|
||||
if (b1->buf == NULL) {
|
||||
OPENSSL_PUT_ERROR(BIO, ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
b1->len = 0;
|
||||
b1->offset = 0;
|
||||
}
|
||||
|
||||
if (b2->buf == NULL) {
|
||||
if (writebuf2_len) {
|
||||
b2->size = writebuf2_len;
|
||||
}
|
||||
b2->buf = OPENSSL_malloc(b2->size);
|
||||
if (b2->buf == NULL) {
|
||||
OPENSSL_PUT_ERROR(BIO, ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
b2->len = 0;
|
||||
b2->offset = 0;
|
||||
}
|
||||
|
||||
b1->peer = bio2;
|
||||
b1->closed = 0;
|
||||
b1->request = 0;
|
||||
b2->peer = bio1;
|
||||
b2->closed = 0;
|
||||
b2->request = 0;
|
||||
|
||||
bio1->init = 1;
|
||||
bio2->init = 1;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static long bio_ctrl(BIO *bio, int cmd, long num, void *ptr) {
|
||||
long ret;
|
||||
struct bio_bio_st *b = bio->ptr;
|
||||
|
||||
assert(b != NULL);
|
||||
|
||||
switch (cmd) {
|
||||
// specific CTRL codes
|
||||
|
||||
case BIO_C_GET_WRITE_BUF_SIZE:
|
||||
ret = (long)b->size;
|
||||
break;
|
||||
|
||||
case BIO_C_GET_WRITE_GUARANTEE:
|
||||
// How many bytes can the caller feed to the next write
|
||||
// without having to keep any?
|
||||
if (b->peer == NULL || b->closed) {
|
||||
ret = 0;
|
||||
} else {
|
||||
ret = (long)b->size - b->len;
|
||||
}
|
||||
break;
|
||||
|
||||
case BIO_C_GET_READ_REQUEST:
|
||||
// If the peer unsuccessfully tried to read, how many bytes
|
||||
// were requested? (As with BIO_CTRL_PENDING, that number
|
||||
// can usually be treated as boolean.)
|
||||
ret = (long)b->request;
|
||||
break;
|
||||
|
||||
case BIO_C_RESET_READ_REQUEST:
|
||||
// Reset request. (Can be useful after read attempts
|
||||
// at the other side that are meant to be non-blocking,
|
||||
// e.g. when probing SSL_read to see if any data is
|
||||
// available.)
|
||||
b->request = 0;
|
||||
ret = 1;
|
||||
break;
|
||||
|
||||
case BIO_C_SHUTDOWN_WR:
|
||||
// similar to shutdown(..., SHUT_WR)
|
||||
b->closed = 1;
|
||||
ret = 1;
|
||||
break;
|
||||
|
||||
// standard CTRL codes follow
|
||||
|
||||
case BIO_CTRL_GET_CLOSE:
|
||||
ret = bio->shutdown;
|
||||
break;
|
||||
|
||||
case BIO_CTRL_SET_CLOSE:
|
||||
bio->shutdown = (int)num;
|
||||
ret = 1;
|
||||
break;
|
||||
|
||||
case BIO_CTRL_PENDING:
|
||||
if (b->peer != NULL) {
|
||||
struct bio_bio_st *peer_b = b->peer->ptr;
|
||||
ret = (long)peer_b->len;
|
||||
} else {
|
||||
ret = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case BIO_CTRL_WPENDING:
|
||||
ret = 0;
|
||||
if (b->buf != NULL) {
|
||||
ret = (long)b->len;
|
||||
}
|
||||
break;
|
||||
|
||||
case BIO_CTRL_FLUSH:
|
||||
ret = 1;
|
||||
break;
|
||||
|
||||
case BIO_CTRL_EOF: {
|
||||
BIO *other_bio = ptr;
|
||||
|
||||
if (other_bio) {
|
||||
struct bio_bio_st *other_b = other_bio->ptr;
|
||||
assert(other_b != NULL);
|
||||
ret = other_b->len == 0 && other_b->closed;
|
||||
} else {
|
||||
ret = 1;
|
||||
}
|
||||
} break;
|
||||
|
||||
default:
|
||||
ret = 0;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static const BIO_METHOD methods_biop = {
|
||||
BIO_TYPE_BIO, "BIO pair", bio_write, bio_read, NULL /* puts */,
|
||||
NULL /* gets */, bio_ctrl, bio_new, bio_free, NULL /* callback_ctrl */,
|
||||
};
|
||||
|
||||
static const BIO_METHOD *bio_s_bio(void) { return &methods_biop; }
|
||||
|
||||
int BIO_new_bio_pair(BIO** bio1_p, size_t writebuf1_len,
|
||||
BIO** bio2_p, size_t writebuf2_len) {
|
||||
BIO *bio1 = BIO_new(bio_s_bio());
|
||||
BIO *bio2 = BIO_new(bio_s_bio());
|
||||
if (bio1 == NULL || bio2 == NULL ||
|
||||
!bio_make_pair(bio1, bio2, writebuf1_len, writebuf2_len)) {
|
||||
BIO_free(bio1);
|
||||
BIO_free(bio2);
|
||||
*bio1_p = NULL;
|
||||
*bio2_p = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
*bio1_p = bio1;
|
||||
*bio2_p = bio2;
|
||||
return 1;
|
||||
}
|
||||
|
||||
size_t BIO_ctrl_get_read_request(BIO *bio) {
|
||||
return BIO_ctrl(bio, BIO_C_GET_READ_REQUEST, 0, NULL);
|
||||
}
|
||||
|
||||
size_t BIO_ctrl_get_write_guarantee(BIO *bio) {
|
||||
return BIO_ctrl(bio, BIO_C_GET_WRITE_GUARANTEE, 0, NULL);
|
||||
}
|
||||
|
||||
int BIO_shutdown_wr(BIO *bio) {
|
||||
return BIO_ctrl(bio, BIO_C_SHUTDOWN_WR, 0, NULL);
|
||||
}
|
||||
+115
@@ -0,0 +1,115 @@
|
||||
/* Copyright (C) 1995-1998 Eric Young ([email protected])
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young ([email protected]).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson ([email protected]).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young ([email protected])"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson ([email protected])"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.] */
|
||||
|
||||
#include <openssl_grpc/bio.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <openssl_grpc/err.h>
|
||||
#include <openssl_grpc/mem.h>
|
||||
|
||||
int BIO_printf(BIO *bio, const char *format, ...) {
|
||||
va_list args;
|
||||
char buf[256], *out, out_malloced = 0;
|
||||
int out_len, ret;
|
||||
|
||||
va_start(args, format);
|
||||
out_len = vsnprintf(buf, sizeof(buf), format, args);
|
||||
va_end(args);
|
||||
|
||||
#if defined(OPENSSL_WINDOWS)
|
||||
// On Windows, vsnprintf returns -1 rather than the requested length on
|
||||
// truncation
|
||||
if (out_len < 0) {
|
||||
va_start(args, format);
|
||||
out_len = _vscprintf(format, args);
|
||||
va_end(args);
|
||||
assert(out_len >= (int)sizeof(buf));
|
||||
}
|
||||
#endif
|
||||
|
||||
if (out_len < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((size_t) out_len >= sizeof(buf)) {
|
||||
const int requested_len = out_len;
|
||||
// The output was truncated. Note that vsnprintf's return value
|
||||
// does not include a trailing NUL, but the buffer must be sized
|
||||
// for it.
|
||||
out = OPENSSL_malloc(requested_len + 1);
|
||||
out_malloced = 1;
|
||||
if (out == NULL) {
|
||||
OPENSSL_PUT_ERROR(BIO, ERR_R_MALLOC_FAILURE);
|
||||
return -1;
|
||||
}
|
||||
va_start(args, format);
|
||||
out_len = vsnprintf(out, requested_len + 1, format, args);
|
||||
va_end(args);
|
||||
assert(out_len == requested_len);
|
||||
} else {
|
||||
out = buf;
|
||||
}
|
||||
|
||||
ret = BIO_write(bio, out, out_len);
|
||||
if (out_malloced) {
|
||||
OPENSSL_free(out);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
+115
@@ -0,0 +1,115 @@
|
||||
/* Copyright (C) 1995-1998 Eric Young ([email protected])
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young ([email protected]).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson ([email protected]).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young ([email protected])"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson ([email protected])"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.] */
|
||||
|
||||
#include <openssl/bio.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/mem.h>
|
||||
|
||||
int BIO_printf(BIO *bio, const char *format, ...) {
|
||||
va_list args;
|
||||
char buf[256], *out, out_malloced = 0;
|
||||
int out_len, ret;
|
||||
|
||||
va_start(args, format);
|
||||
out_len = vsnprintf(buf, sizeof(buf), format, args);
|
||||
va_end(args);
|
||||
|
||||
#if defined(OPENSSL_WINDOWS)
|
||||
// On Windows, vsnprintf returns -1 rather than the requested length on
|
||||
// truncation
|
||||
if (out_len < 0) {
|
||||
va_start(args, format);
|
||||
out_len = _vscprintf(format, args);
|
||||
va_end(args);
|
||||
assert(out_len >= (int)sizeof(buf));
|
||||
}
|
||||
#endif
|
||||
|
||||
if (out_len < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((size_t) out_len >= sizeof(buf)) {
|
||||
const int requested_len = out_len;
|
||||
// The output was truncated. Note that vsnprintf's return value
|
||||
// does not include a trailing NUL, but the buffer must be sized
|
||||
// for it.
|
||||
out = OPENSSL_malloc(requested_len + 1);
|
||||
out_malloced = 1;
|
||||
if (out == NULL) {
|
||||
OPENSSL_PUT_ERROR(BIO, ERR_R_MALLOC_FAILURE);
|
||||
return -1;
|
||||
}
|
||||
va_start(args, format);
|
||||
out_len = vsnprintf(out, requested_len + 1, format, args);
|
||||
va_end(args);
|
||||
assert(out_len == requested_len);
|
||||
} else {
|
||||
out = buf;
|
||||
}
|
||||
|
||||
ret = BIO_write(bio, out, out_len);
|
||||
if (out_malloced) {
|
||||
OPENSSL_free(out);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
+206
@@ -0,0 +1,206 @@
|
||||
/* crypto/bio/bss_sock.c */
|
||||
/* Copyright (C) 1995-1998 Eric Young ([email protected])
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young ([email protected]).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson ([email protected]).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young ([email protected])"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson ([email protected])"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.] */
|
||||
|
||||
#include <openssl_grpc/bio.h>
|
||||
|
||||
#if !defined(OPENSSL_TRUSTY)
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
|
||||
#if !defined(OPENSSL_WINDOWS)
|
||||
#include <unistd.h>
|
||||
#else
|
||||
OPENSSL_MSVC_PRAGMA(warning(push, 3))
|
||||
#include <winsock2.h>
|
||||
OPENSSL_MSVC_PRAGMA(warning(pop))
|
||||
|
||||
OPENSSL_MSVC_PRAGMA(comment(lib, "Ws2_32.lib"))
|
||||
#endif
|
||||
|
||||
#include "internal.h"
|
||||
|
||||
|
||||
#if !defined(OPENSSL_WINDOWS)
|
||||
static int closesocket(int sock) {
|
||||
return close(sock);
|
||||
}
|
||||
#endif
|
||||
|
||||
static int sock_new(BIO *bio) {
|
||||
bio->init = 0;
|
||||
bio->num = 0;
|
||||
bio->ptr = NULL;
|
||||
bio->flags = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int sock_free(BIO *bio) {
|
||||
if (bio == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (bio->shutdown) {
|
||||
if (bio->init) {
|
||||
closesocket(bio->num);
|
||||
}
|
||||
bio->init = 0;
|
||||
bio->flags = 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int sock_read(BIO *b, char *out, int outl) {
|
||||
int ret = 0;
|
||||
|
||||
if (out == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
bio_clear_socket_error();
|
||||
#if defined(OPENSSL_WINDOWS)
|
||||
ret = recv(b->num, out, outl, 0);
|
||||
#else
|
||||
ret = read(b->num, out, outl);
|
||||
#endif
|
||||
BIO_clear_retry_flags(b);
|
||||
if (ret <= 0) {
|
||||
if (bio_fd_should_retry(ret)) {
|
||||
BIO_set_retry_read(b);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int sock_write(BIO *b, const char *in, int inl) {
|
||||
int ret;
|
||||
|
||||
bio_clear_socket_error();
|
||||
#if defined(OPENSSL_WINDOWS)
|
||||
ret = send(b->num, in, inl, 0);
|
||||
#else
|
||||
ret = write(b->num, in, inl);
|
||||
#endif
|
||||
BIO_clear_retry_flags(b);
|
||||
if (ret <= 0) {
|
||||
if (bio_fd_should_retry(ret)) {
|
||||
BIO_set_retry_write(b);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static long sock_ctrl(BIO *b, int cmd, long num, void *ptr) {
|
||||
long ret = 1;
|
||||
int *ip;
|
||||
|
||||
switch (cmd) {
|
||||
case BIO_C_SET_FD:
|
||||
sock_free(b);
|
||||
b->num = *((int *)ptr);
|
||||
b->shutdown = (int)num;
|
||||
b->init = 1;
|
||||
break;
|
||||
case BIO_C_GET_FD:
|
||||
if (b->init) {
|
||||
ip = (int *)ptr;
|
||||
if (ip != NULL) {
|
||||
*ip = b->num;
|
||||
}
|
||||
ret = b->num;
|
||||
} else {
|
||||
ret = -1;
|
||||
}
|
||||
break;
|
||||
case BIO_CTRL_GET_CLOSE:
|
||||
ret = b->shutdown;
|
||||
break;
|
||||
case BIO_CTRL_SET_CLOSE:
|
||||
b->shutdown = (int)num;
|
||||
break;
|
||||
case BIO_CTRL_FLUSH:
|
||||
ret = 1;
|
||||
break;
|
||||
default:
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const BIO_METHOD methods_sockp = {
|
||||
BIO_TYPE_SOCKET, "socket",
|
||||
sock_write, sock_read,
|
||||
NULL /* puts */, NULL /* gets, */,
|
||||
sock_ctrl, sock_new,
|
||||
sock_free, NULL /* callback_ctrl */,
|
||||
};
|
||||
|
||||
const BIO_METHOD *BIO_s_socket(void) { return &methods_sockp; }
|
||||
|
||||
BIO *BIO_new_socket(int fd, int close_flag) {
|
||||
BIO *ret;
|
||||
|
||||
ret = BIO_new(BIO_s_socket());
|
||||
if (ret == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
BIO_set_fd(ret, fd, close_flag);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif // OPENSSL_TRUSTY
|
||||
+206
@@ -0,0 +1,206 @@
|
||||
/* crypto/bio/bss_sock.c */
|
||||
/* Copyright (C) 1995-1998 Eric Young ([email protected])
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young ([email protected]).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson ([email protected]).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young ([email protected])"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson ([email protected])"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.] */
|
||||
|
||||
#include <openssl/bio.h>
|
||||
|
||||
#if !defined(OPENSSL_TRUSTY)
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
|
||||
#if !defined(OPENSSL_WINDOWS)
|
||||
#include <unistd.h>
|
||||
#else
|
||||
OPENSSL_MSVC_PRAGMA(warning(push, 3))
|
||||
#include <winsock2.h>
|
||||
OPENSSL_MSVC_PRAGMA(warning(pop))
|
||||
|
||||
OPENSSL_MSVC_PRAGMA(comment(lib, "Ws2_32.lib"))
|
||||
#endif
|
||||
|
||||
#include "internal.h"
|
||||
|
||||
|
||||
#if !defined(OPENSSL_WINDOWS)
|
||||
static int closesocket(int sock) {
|
||||
return close(sock);
|
||||
}
|
||||
#endif
|
||||
|
||||
static int sock_new(BIO *bio) {
|
||||
bio->init = 0;
|
||||
bio->num = 0;
|
||||
bio->ptr = NULL;
|
||||
bio->flags = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int sock_free(BIO *bio) {
|
||||
if (bio == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (bio->shutdown) {
|
||||
if (bio->init) {
|
||||
closesocket(bio->num);
|
||||
}
|
||||
bio->init = 0;
|
||||
bio->flags = 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int sock_read(BIO *b, char *out, int outl) {
|
||||
int ret = 0;
|
||||
|
||||
if (out == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
bio_clear_socket_error();
|
||||
#if defined(OPENSSL_WINDOWS)
|
||||
ret = recv(b->num, out, outl, 0);
|
||||
#else
|
||||
ret = read(b->num, out, outl);
|
||||
#endif
|
||||
BIO_clear_retry_flags(b);
|
||||
if (ret <= 0) {
|
||||
if (bio_fd_should_retry(ret)) {
|
||||
BIO_set_retry_read(b);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int sock_write(BIO *b, const char *in, int inl) {
|
||||
int ret;
|
||||
|
||||
bio_clear_socket_error();
|
||||
#if defined(OPENSSL_WINDOWS)
|
||||
ret = send(b->num, in, inl, 0);
|
||||
#else
|
||||
ret = write(b->num, in, inl);
|
||||
#endif
|
||||
BIO_clear_retry_flags(b);
|
||||
if (ret <= 0) {
|
||||
if (bio_fd_should_retry(ret)) {
|
||||
BIO_set_retry_write(b);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static long sock_ctrl(BIO *b, int cmd, long num, void *ptr) {
|
||||
long ret = 1;
|
||||
int *ip;
|
||||
|
||||
switch (cmd) {
|
||||
case BIO_C_SET_FD:
|
||||
sock_free(b);
|
||||
b->num = *((int *)ptr);
|
||||
b->shutdown = (int)num;
|
||||
b->init = 1;
|
||||
break;
|
||||
case BIO_C_GET_FD:
|
||||
if (b->init) {
|
||||
ip = (int *)ptr;
|
||||
if (ip != NULL) {
|
||||
*ip = b->num;
|
||||
}
|
||||
ret = b->num;
|
||||
} else {
|
||||
ret = -1;
|
||||
}
|
||||
break;
|
||||
case BIO_CTRL_GET_CLOSE:
|
||||
ret = b->shutdown;
|
||||
break;
|
||||
case BIO_CTRL_SET_CLOSE:
|
||||
b->shutdown = (int)num;
|
||||
break;
|
||||
case BIO_CTRL_FLUSH:
|
||||
ret = 1;
|
||||
break;
|
||||
default:
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const BIO_METHOD methods_sockp = {
|
||||
BIO_TYPE_SOCKET, "socket",
|
||||
sock_write, sock_read,
|
||||
NULL /* puts */, NULL /* gets, */,
|
||||
sock_ctrl, sock_new,
|
||||
sock_free, NULL /* callback_ctrl */,
|
||||
};
|
||||
|
||||
const BIO_METHOD *BIO_s_socket(void) { return &methods_sockp; }
|
||||
|
||||
BIO *BIO_new_socket(int fd, int close_flag) {
|
||||
BIO *ret;
|
||||
|
||||
ret = BIO_new(BIO_s_socket());
|
||||
if (ret == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
BIO_set_fd(ret, fd, close_flag);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif // OPENSSL_TRUSTY
|
||||
+118
@@ -0,0 +1,118 @@
|
||||
/* Copyright (c) 2014, Google Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
||||
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
|
||||
|
||||
#undef _POSIX_C_SOURCE
|
||||
#define _POSIX_C_SOURCE 200112L
|
||||
|
||||
#include <openssl_grpc/bio.h>
|
||||
#include <openssl_grpc/err.h>
|
||||
|
||||
#if !defined(OPENSSL_TRUSTY)
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#if !defined(OPENSSL_WINDOWS)
|
||||
#include <netdb.h>
|
||||
#include <unistd.h>
|
||||
#else
|
||||
OPENSSL_MSVC_PRAGMA(warning(push, 3))
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
OPENSSL_MSVC_PRAGMA(warning(pop))
|
||||
#endif
|
||||
|
||||
#include "internal.h"
|
||||
#include "../internal.h"
|
||||
|
||||
|
||||
int bio_ip_and_port_to_socket_and_addr(int *out_sock,
|
||||
struct sockaddr_storage *out_addr,
|
||||
socklen_t *out_addr_length,
|
||||
const char *hostname,
|
||||
const char *port_str) {
|
||||
struct addrinfo hint, *result, *cur;
|
||||
int ret;
|
||||
|
||||
*out_sock = -1;
|
||||
|
||||
OPENSSL_memset(&hint, 0, sizeof(hint));
|
||||
hint.ai_family = AF_UNSPEC;
|
||||
hint.ai_socktype = SOCK_STREAM;
|
||||
|
||||
ret = getaddrinfo(hostname, port_str, &hint, &result);
|
||||
if (ret != 0) {
|
||||
OPENSSL_PUT_ERROR(SYS, 0);
|
||||
ERR_add_error_data(1, gai_strerror(ret));
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
|
||||
for (cur = result; cur; cur = cur->ai_next) {
|
||||
if ((size_t) cur->ai_addrlen > sizeof(struct sockaddr_storage)) {
|
||||
continue;
|
||||
}
|
||||
OPENSSL_memset(out_addr, 0, sizeof(struct sockaddr_storage));
|
||||
OPENSSL_memcpy(out_addr, cur->ai_addr, cur->ai_addrlen);
|
||||
*out_addr_length = cur->ai_addrlen;
|
||||
|
||||
*out_sock = socket(cur->ai_family, cur->ai_socktype, cur->ai_protocol);
|
||||
if (*out_sock < 0) {
|
||||
OPENSSL_PUT_SYSTEM_ERROR();
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
out:
|
||||
freeaddrinfo(result);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int bio_socket_nbio(int sock, int on) {
|
||||
#if defined(OPENSSL_WINDOWS)
|
||||
u_long arg = on;
|
||||
|
||||
return 0 == ioctlsocket(sock, FIONBIO, &arg);
|
||||
#else
|
||||
int flags = fcntl(sock, F_GETFL, 0);
|
||||
if (flags < 0) {
|
||||
return 0;
|
||||
}
|
||||
if (!on) {
|
||||
flags &= ~O_NONBLOCK;
|
||||
} else {
|
||||
flags |= O_NONBLOCK;
|
||||
}
|
||||
return fcntl(sock, F_SETFL, flags) == 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
void bio_clear_socket_error(void) {}
|
||||
|
||||
int bio_sock_error(int sock) {
|
||||
int error;
|
||||
socklen_t error_size = sizeof(error);
|
||||
|
||||
if (getsockopt(sock, SOL_SOCKET, SO_ERROR, (char *)&error, &error_size) < 0) {
|
||||
return 1;
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
#endif // OPENSSL_TRUSTY
|
||||
@@ -0,0 +1,118 @@
|
||||
/* Copyright (c) 2014, Google Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
||||
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
|
||||
|
||||
#undef _POSIX_C_SOURCE
|
||||
#define _POSIX_C_SOURCE 200112L
|
||||
|
||||
#include <openssl/bio.h>
|
||||
#include <openssl/err.h>
|
||||
|
||||
#if !defined(OPENSSL_TRUSTY)
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#if !defined(OPENSSL_WINDOWS)
|
||||
#include <netdb.h>
|
||||
#include <unistd.h>
|
||||
#else
|
||||
OPENSSL_MSVC_PRAGMA(warning(push, 3))
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
OPENSSL_MSVC_PRAGMA(warning(pop))
|
||||
#endif
|
||||
|
||||
#include "internal.h"
|
||||
#include "../internal.h"
|
||||
|
||||
|
||||
int bio_ip_and_port_to_socket_and_addr(int *out_sock,
|
||||
struct sockaddr_storage *out_addr,
|
||||
socklen_t *out_addr_length,
|
||||
const char *hostname,
|
||||
const char *port_str) {
|
||||
struct addrinfo hint, *result, *cur;
|
||||
int ret;
|
||||
|
||||
*out_sock = -1;
|
||||
|
||||
OPENSSL_memset(&hint, 0, sizeof(hint));
|
||||
hint.ai_family = AF_UNSPEC;
|
||||
hint.ai_socktype = SOCK_STREAM;
|
||||
|
||||
ret = getaddrinfo(hostname, port_str, &hint, &result);
|
||||
if (ret != 0) {
|
||||
OPENSSL_PUT_ERROR(SYS, 0);
|
||||
ERR_add_error_data(1, gai_strerror(ret));
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
|
||||
for (cur = result; cur; cur = cur->ai_next) {
|
||||
if ((size_t) cur->ai_addrlen > sizeof(struct sockaddr_storage)) {
|
||||
continue;
|
||||
}
|
||||
OPENSSL_memset(out_addr, 0, sizeof(struct sockaddr_storage));
|
||||
OPENSSL_memcpy(out_addr, cur->ai_addr, cur->ai_addrlen);
|
||||
*out_addr_length = cur->ai_addrlen;
|
||||
|
||||
*out_sock = socket(cur->ai_family, cur->ai_socktype, cur->ai_protocol);
|
||||
if (*out_sock < 0) {
|
||||
OPENSSL_PUT_SYSTEM_ERROR();
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
out:
|
||||
freeaddrinfo(result);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int bio_socket_nbio(int sock, int on) {
|
||||
#if defined(OPENSSL_WINDOWS)
|
||||
u_long arg = on;
|
||||
|
||||
return 0 == ioctlsocket(sock, FIONBIO, &arg);
|
||||
#else
|
||||
int flags = fcntl(sock, F_GETFL, 0);
|
||||
if (flags < 0) {
|
||||
return 0;
|
||||
}
|
||||
if (!on) {
|
||||
flags &= ~O_NONBLOCK;
|
||||
} else {
|
||||
flags |= O_NONBLOCK;
|
||||
}
|
||||
return fcntl(sock, F_SETFL, flags) == 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
void bio_clear_socket_error(void) {}
|
||||
|
||||
int bio_sock_error(int sock) {
|
||||
int error;
|
||||
socklen_t error_size = sizeof(error);
|
||||
|
||||
if (getsockopt(sock, SOL_SOCKET, SO_ERROR, (char *)&error, &error_size) < 0) {
|
||||
return 1;
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
#endif // OPENSSL_TRUSTY
|
||||
+64
@@ -0,0 +1,64 @@
|
||||
/* Copyright (c) 2015, Google Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
||||
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
|
||||
|
||||
#include <openssl_grpc/bn.h>
|
||||
|
||||
#include <openssl_grpc/bytestring.h>
|
||||
#include <openssl_grpc/err.h>
|
||||
|
||||
|
||||
int BN_parse_asn1_unsigned(CBS *cbs, BIGNUM *ret) {
|
||||
CBS child;
|
||||
if (!CBS_get_asn1(cbs, &child, CBS_ASN1_INTEGER) ||
|
||||
CBS_len(&child) == 0) {
|
||||
OPENSSL_PUT_ERROR(BN, BN_R_BAD_ENCODING);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (CBS_data(&child)[0] & 0x80) {
|
||||
OPENSSL_PUT_ERROR(BN, BN_R_NEGATIVE_NUMBER);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// INTEGERs must be minimal.
|
||||
if (CBS_data(&child)[0] == 0x00 &&
|
||||
CBS_len(&child) > 1 &&
|
||||
!(CBS_data(&child)[1] & 0x80)) {
|
||||
OPENSSL_PUT_ERROR(BN, BN_R_BAD_ENCODING);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return BN_bin2bn(CBS_data(&child), CBS_len(&child), ret) != NULL;
|
||||
}
|
||||
|
||||
int BN_marshal_asn1(CBB *cbb, const BIGNUM *bn) {
|
||||
// Negative numbers are unsupported.
|
||||
if (BN_is_negative(bn)) {
|
||||
OPENSSL_PUT_ERROR(BN, BN_R_NEGATIVE_NUMBER);
|
||||
return 0;
|
||||
}
|
||||
|
||||
CBB child;
|
||||
if (!CBB_add_asn1(cbb, &child, CBS_ASN1_INTEGER) ||
|
||||
// The number must be padded with a leading zero if the high bit would
|
||||
// otherwise be set or if |bn| is zero.
|
||||
(BN_num_bits(bn) % 8 == 0 && !CBB_add_u8(&child, 0x00)) ||
|
||||
!BN_bn2cbb_padded(&child, BN_num_bytes(bn), bn) ||
|
||||
!CBB_flush(cbb)) {
|
||||
OPENSSL_PUT_ERROR(BN, BN_R_ENCODE_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
/* Copyright (c) 2015, Google Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
||||
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
|
||||
|
||||
#include <openssl/bn.h>
|
||||
|
||||
#include <openssl/bytestring.h>
|
||||
#include <openssl/err.h>
|
||||
|
||||
|
||||
int BN_parse_asn1_unsigned(CBS *cbs, BIGNUM *ret) {
|
||||
CBS child;
|
||||
if (!CBS_get_asn1(cbs, &child, CBS_ASN1_INTEGER) ||
|
||||
CBS_len(&child) == 0) {
|
||||
OPENSSL_PUT_ERROR(BN, BN_R_BAD_ENCODING);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (CBS_data(&child)[0] & 0x80) {
|
||||
OPENSSL_PUT_ERROR(BN, BN_R_NEGATIVE_NUMBER);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// INTEGERs must be minimal.
|
||||
if (CBS_data(&child)[0] == 0x00 &&
|
||||
CBS_len(&child) > 1 &&
|
||||
!(CBS_data(&child)[1] & 0x80)) {
|
||||
OPENSSL_PUT_ERROR(BN, BN_R_BAD_ENCODING);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return BN_bin2bn(CBS_data(&child), CBS_len(&child), ret) != NULL;
|
||||
}
|
||||
|
||||
int BN_marshal_asn1(CBB *cbb, const BIGNUM *bn) {
|
||||
// Negative numbers are unsupported.
|
||||
if (BN_is_negative(bn)) {
|
||||
OPENSSL_PUT_ERROR(BN, BN_R_NEGATIVE_NUMBER);
|
||||
return 0;
|
||||
}
|
||||
|
||||
CBB child;
|
||||
if (!CBB_add_asn1(cbb, &child, CBS_ASN1_INTEGER) ||
|
||||
// The number must be padded with a leading zero if the high bit would
|
||||
// otherwise be set or if |bn| is zero.
|
||||
(BN_num_bits(bn) % 8 == 0 && !CBB_add_u8(&child, 0x00)) ||
|
||||
!BN_bn2cbb_padded(&child, BN_num_bytes(bn), bn) ||
|
||||
!CBB_flush(cbb)) {
|
||||
OPENSSL_PUT_ERROR(BN, BN_R_ENCODE_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
+470
@@ -0,0 +1,470 @@
|
||||
/* Copyright (C) 1995-1998 Eric Young ([email protected])
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young (eay@cryptsoft.com).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young (eay@cryptsoft.com)"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson ([email protected])"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.] */
|
||||
|
||||
#include <openssl_grpc/bn.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <ctype.h>
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <openssl_grpc/bio.h>
|
||||
#include <openssl_grpc/bytestring.h>
|
||||
#include <openssl_grpc/err.h>
|
||||
#include <openssl_grpc/mem.h>
|
||||
|
||||
#include "../fipsmodule/bn/internal.h"
|
||||
|
||||
|
||||
int BN_bn2cbb_padded(CBB *out, size_t len, const BIGNUM *in) {
|
||||
uint8_t *ptr;
|
||||
return CBB_add_space(out, &ptr, len) && BN_bn2bin_padded(ptr, len, in);
|
||||
}
|
||||
|
||||
static const char hextable[] = "0123456789abcdef";
|
||||
|
||||
char *BN_bn2hex(const BIGNUM *bn) {
|
||||
int width = bn_minimal_width(bn);
|
||||
char *buf = OPENSSL_malloc(1 /* leading '-' */ + 1 /* zero is non-empty */ +
|
||||
width * BN_BYTES * 2 + 1 /* trailing NUL */);
|
||||
if (buf == NULL) {
|
||||
OPENSSL_PUT_ERROR(BN, ERR_R_MALLOC_FAILURE);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char *p = buf;
|
||||
if (bn->neg) {
|
||||
*(p++) = '-';
|
||||
}
|
||||
|
||||
if (BN_is_zero(bn)) {
|
||||
*(p++) = '0';
|
||||
}
|
||||
|
||||
int z = 0;
|
||||
for (int i = width - 1; i >= 0; i--) {
|
||||
for (int j = BN_BITS2 - 8; j >= 0; j -= 8) {
|
||||
// strip leading zeros
|
||||
int v = ((int)(bn->d[i] >> (long)j)) & 0xff;
|
||||
if (z || v != 0) {
|
||||
*(p++) = hextable[v >> 4];
|
||||
*(p++) = hextable[v & 0x0f];
|
||||
z = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
*p = '\0';
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
// decode_hex decodes |in_len| bytes of hex data from |in| and updates |bn|.
|
||||
static int decode_hex(BIGNUM *bn, const char *in, int in_len) {
|
||||
if (in_len > INT_MAX/4) {
|
||||
OPENSSL_PUT_ERROR(BN, BN_R_BIGNUM_TOO_LONG);
|
||||
return 0;
|
||||
}
|
||||
// |in_len| is the number of hex digits.
|
||||
if (!bn_expand(bn, in_len * 4)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int i = 0;
|
||||
while (in_len > 0) {
|
||||
// Decode one |BN_ULONG| at a time.
|
||||
int todo = BN_BYTES * 2;
|
||||
if (todo > in_len) {
|
||||
todo = in_len;
|
||||
}
|
||||
|
||||
BN_ULONG word = 0;
|
||||
int j;
|
||||
for (j = todo; j > 0; j--) {
|
||||
char c = in[in_len - j];
|
||||
|
||||
BN_ULONG hex;
|
||||
if (c >= '0' && c <= '9') {
|
||||
hex = c - '0';
|
||||
} else if (c >= 'a' && c <= 'f') {
|
||||
hex = c - 'a' + 10;
|
||||
} else if (c >= 'A' && c <= 'F') {
|
||||
hex = c - 'A' + 10;
|
||||
} else {
|
||||
hex = 0;
|
||||
// This shouldn't happen. The caller checks |isxdigit|.
|
||||
assert(0);
|
||||
}
|
||||
word = (word << 4) | hex;
|
||||
}
|
||||
|
||||
bn->d[i++] = word;
|
||||
in_len -= todo;
|
||||
}
|
||||
assert(i <= bn->dmax);
|
||||
bn->width = i;
|
||||
return 1;
|
||||
}
|
||||
|
||||
// decode_dec decodes |in_len| bytes of decimal data from |in| and updates |bn|.
|
||||
static int decode_dec(BIGNUM *bn, const char *in, int in_len) {
|
||||
int i, j;
|
||||
BN_ULONG l = 0;
|
||||
|
||||
// Decode |BN_DEC_NUM| digits at a time.
|
||||
j = BN_DEC_NUM - (in_len % BN_DEC_NUM);
|
||||
if (j == BN_DEC_NUM) {
|
||||
j = 0;
|
||||
}
|
||||
l = 0;
|
||||
for (i = 0; i < in_len; i++) {
|
||||
l *= 10;
|
||||
l += in[i] - '0';
|
||||
if (++j == BN_DEC_NUM) {
|
||||
if (!BN_mul_word(bn, BN_DEC_CONV) ||
|
||||
!BN_add_word(bn, l)) {
|
||||
return 0;
|
||||
}
|
||||
l = 0;
|
||||
j = 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
typedef int (*decode_func) (BIGNUM *bn, const char *in, int in_len);
|
||||
typedef int (*char_test_func) (int c);
|
||||
|
||||
static int bn_x2bn(BIGNUM **outp, const char *in, decode_func decode, char_test_func want_char) {
|
||||
BIGNUM *ret = NULL;
|
||||
int neg = 0, i;
|
||||
int num;
|
||||
|
||||
if (in == NULL || *in == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (*in == '-') {
|
||||
neg = 1;
|
||||
in++;
|
||||
}
|
||||
|
||||
for (i = 0; want_char((unsigned char)in[i]) && i + neg < INT_MAX; i++) {}
|
||||
|
||||
num = i + neg;
|
||||
if (outp == NULL) {
|
||||
return num;
|
||||
}
|
||||
|
||||
// in is the start of the hex digits, and it is 'i' long
|
||||
if (*outp == NULL) {
|
||||
ret = BN_new();
|
||||
if (ret == NULL) {
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
ret = *outp;
|
||||
BN_zero(ret);
|
||||
}
|
||||
|
||||
if (!decode(ret, in, i)) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
bn_set_minimal_width(ret);
|
||||
if (!BN_is_zero(ret)) {
|
||||
ret->neg = neg;
|
||||
}
|
||||
|
||||
*outp = ret;
|
||||
return num;
|
||||
|
||||
err:
|
||||
if (*outp == NULL) {
|
||||
BN_free(ret);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int BN_hex2bn(BIGNUM **outp, const char *in) {
|
||||
return bn_x2bn(outp, in, decode_hex, isxdigit);
|
||||
}
|
||||
|
||||
char *BN_bn2dec(const BIGNUM *a) {
|
||||
// It is easier to print strings little-endian, so we assemble it in reverse
|
||||
// and fix at the end.
|
||||
BIGNUM *copy = NULL;
|
||||
CBB cbb;
|
||||
if (!CBB_init(&cbb, 16) ||
|
||||
!CBB_add_u8(&cbb, 0 /* trailing NUL */)) {
|
||||
goto cbb_err;
|
||||
}
|
||||
|
||||
if (BN_is_zero(a)) {
|
||||
if (!CBB_add_u8(&cbb, '0')) {
|
||||
goto cbb_err;
|
||||
}
|
||||
} else {
|
||||
copy = BN_dup(a);
|
||||
if (copy == NULL) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
while (!BN_is_zero(copy)) {
|
||||
BN_ULONG word = BN_div_word(copy, BN_DEC_CONV);
|
||||
if (word == (BN_ULONG)-1) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
const int add_leading_zeros = !BN_is_zero(copy);
|
||||
for (int i = 0; i < BN_DEC_NUM && (add_leading_zeros || word != 0); i++) {
|
||||
if (!CBB_add_u8(&cbb, '0' + word % 10)) {
|
||||
goto cbb_err;
|
||||
}
|
||||
word /= 10;
|
||||
}
|
||||
assert(word == 0);
|
||||
}
|
||||
}
|
||||
|
||||
if (BN_is_negative(a) &&
|
||||
!CBB_add_u8(&cbb, '-')) {
|
||||
goto cbb_err;
|
||||
}
|
||||
|
||||
uint8_t *data;
|
||||
size_t len;
|
||||
if (!CBB_finish(&cbb, &data, &len)) {
|
||||
goto cbb_err;
|
||||
}
|
||||
|
||||
// Reverse the buffer.
|
||||
for (size_t i = 0; i < len/2; i++) {
|
||||
uint8_t tmp = data[i];
|
||||
data[i] = data[len - 1 - i];
|
||||
data[len - 1 - i] = tmp;
|
||||
}
|
||||
|
||||
BN_free(copy);
|
||||
return (char *)data;
|
||||
|
||||
cbb_err:
|
||||
OPENSSL_PUT_ERROR(BN, ERR_R_MALLOC_FAILURE);
|
||||
err:
|
||||
BN_free(copy);
|
||||
CBB_cleanup(&cbb);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int BN_dec2bn(BIGNUM **outp, const char *in) {
|
||||
return bn_x2bn(outp, in, decode_dec, isdigit);
|
||||
}
|
||||
|
||||
int BN_asc2bn(BIGNUM **outp, const char *in) {
|
||||
const char *const orig_in = in;
|
||||
if (*in == '-') {
|
||||
in++;
|
||||
}
|
||||
|
||||
if (in[0] == '0' && (in[1] == 'X' || in[1] == 'x')) {
|
||||
if (!BN_hex2bn(outp, in+2)) {
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
if (!BN_dec2bn(outp, in)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (*orig_in == '-' && !BN_is_zero(*outp)) {
|
||||
(*outp)->neg = 1;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int BN_print(BIO *bp, const BIGNUM *a) {
|
||||
int i, j, v, z = 0;
|
||||
int ret = 0;
|
||||
|
||||
if (a->neg && BIO_write(bp, "-", 1) != 1) {
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (BN_is_zero(a) && BIO_write(bp, "0", 1) != 1) {
|
||||
goto end;
|
||||
}
|
||||
|
||||
for (i = bn_minimal_width(a) - 1; i >= 0; i--) {
|
||||
for (j = BN_BITS2 - 4; j >= 0; j -= 4) {
|
||||
// strip leading zeros
|
||||
v = ((int)(a->d[i] >> (long)j)) & 0x0f;
|
||||
if (z || v != 0) {
|
||||
if (BIO_write(bp, &hextable[v], 1) != 1) {
|
||||
goto end;
|
||||
}
|
||||
z = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
ret = 1;
|
||||
|
||||
end:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int BN_print_fp(FILE *fp, const BIGNUM *a) {
|
||||
BIO *b = BIO_new_fp(fp, BIO_NOCLOSE);
|
||||
if (b == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ret = BN_print(b, a);
|
||||
BIO_free(b);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
size_t BN_bn2mpi(const BIGNUM *in, uint8_t *out) {
|
||||
const size_t bits = BN_num_bits(in);
|
||||
const size_t bytes = (bits + 7) / 8;
|
||||
// If the number of bits is a multiple of 8, i.e. if the MSB is set,
|
||||
// prefix with a zero byte.
|
||||
int extend = 0;
|
||||
if (bytes != 0 && (bits & 0x07) == 0) {
|
||||
extend = 1;
|
||||
}
|
||||
|
||||
const size_t len = bytes + extend;
|
||||
if (len < bytes ||
|
||||
4 + len < len ||
|
||||
(len & 0xffffffff) != len) {
|
||||
// If we cannot represent the number then we emit zero as the interface
|
||||
// doesn't allow an error to be signalled.
|
||||
if (out) {
|
||||
OPENSSL_memset(out, 0, 4);
|
||||
}
|
||||
return 4;
|
||||
}
|
||||
|
||||
if (out == NULL) {
|
||||
return 4 + len;
|
||||
}
|
||||
|
||||
out[0] = len >> 24;
|
||||
out[1] = len >> 16;
|
||||
out[2] = len >> 8;
|
||||
out[3] = len;
|
||||
if (extend) {
|
||||
out[4] = 0;
|
||||
}
|
||||
BN_bn2bin(in, out + 4 + extend);
|
||||
if (in->neg && len > 0) {
|
||||
out[4] |= 0x80;
|
||||
}
|
||||
return len + 4;
|
||||
}
|
||||
|
||||
BIGNUM *BN_mpi2bn(const uint8_t *in, size_t len, BIGNUM *out) {
|
||||
if (len < 4) {
|
||||
OPENSSL_PUT_ERROR(BN, BN_R_BAD_ENCODING);
|
||||
return NULL;
|
||||
}
|
||||
const size_t in_len = ((size_t)in[0] << 24) |
|
||||
((size_t)in[1] << 16) |
|
||||
((size_t)in[2] << 8) |
|
||||
((size_t)in[3]);
|
||||
if (in_len != len - 4) {
|
||||
OPENSSL_PUT_ERROR(BN, BN_R_BAD_ENCODING);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int out_is_alloced = 0;
|
||||
if (out == NULL) {
|
||||
out = BN_new();
|
||||
if (out == NULL) {
|
||||
OPENSSL_PUT_ERROR(BN, ERR_R_MALLOC_FAILURE);
|
||||
return NULL;
|
||||
}
|
||||
out_is_alloced = 1;
|
||||
}
|
||||
|
||||
if (in_len == 0) {
|
||||
BN_zero(out);
|
||||
return out;
|
||||
}
|
||||
|
||||
in += 4;
|
||||
if (BN_bin2bn(in, in_len, out) == NULL) {
|
||||
if (out_is_alloced) {
|
||||
BN_free(out);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
out->neg = ((*in) & 0x80) != 0;
|
||||
if (out->neg) {
|
||||
BN_clear_bit(out, BN_num_bits(out) - 1);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
int BN_bn2binpad(const BIGNUM *in, uint8_t *out, int len) {
|
||||
if (len < 0 ||
|
||||
!BN_bn2bin_padded(out, (size_t)len, in)) {
|
||||
return -1;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
@@ -0,0 +1,470 @@
|
||||
/* Copyright (C) 1995-1998 Eric Young ([email protected])
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young ([email protected]).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson ([email protected]).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young ([email protected])"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson ([email protected])"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.] */
|
||||
|
||||
#include <openssl/bn.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <ctype.h>
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <openssl/bio.h>
|
||||
#include <openssl/bytestring.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/mem.h>
|
||||
|
||||
#include "../fipsmodule/bn/internal.h"
|
||||
|
||||
|
||||
int BN_bn2cbb_padded(CBB *out, size_t len, const BIGNUM *in) {
|
||||
uint8_t *ptr;
|
||||
return CBB_add_space(out, &ptr, len) && BN_bn2bin_padded(ptr, len, in);
|
||||
}
|
||||
|
||||
static const char hextable[] = "0123456789abcdef";
|
||||
|
||||
char *BN_bn2hex(const BIGNUM *bn) {
|
||||
int width = bn_minimal_width(bn);
|
||||
char *buf = OPENSSL_malloc(1 /* leading '-' */ + 1 /* zero is non-empty */ +
|
||||
width * BN_BYTES * 2 + 1 /* trailing NUL */);
|
||||
if (buf == NULL) {
|
||||
OPENSSL_PUT_ERROR(BN, ERR_R_MALLOC_FAILURE);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char *p = buf;
|
||||
if (bn->neg) {
|
||||
*(p++) = '-';
|
||||
}
|
||||
|
||||
if (BN_is_zero(bn)) {
|
||||
*(p++) = '0';
|
||||
}
|
||||
|
||||
int z = 0;
|
||||
for (int i = width - 1; i >= 0; i--) {
|
||||
for (int j = BN_BITS2 - 8; j >= 0; j -= 8) {
|
||||
// strip leading zeros
|
||||
int v = ((int)(bn->d[i] >> (long)j)) & 0xff;
|
||||
if (z || v != 0) {
|
||||
*(p++) = hextable[v >> 4];
|
||||
*(p++) = hextable[v & 0x0f];
|
||||
z = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
*p = '\0';
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
// decode_hex decodes |in_len| bytes of hex data from |in| and updates |bn|.
|
||||
static int decode_hex(BIGNUM *bn, const char *in, int in_len) {
|
||||
if (in_len > INT_MAX/4) {
|
||||
OPENSSL_PUT_ERROR(BN, BN_R_BIGNUM_TOO_LONG);
|
||||
return 0;
|
||||
}
|
||||
// |in_len| is the number of hex digits.
|
||||
if (!bn_expand(bn, in_len * 4)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int i = 0;
|
||||
while (in_len > 0) {
|
||||
// Decode one |BN_ULONG| at a time.
|
||||
int todo = BN_BYTES * 2;
|
||||
if (todo > in_len) {
|
||||
todo = in_len;
|
||||
}
|
||||
|
||||
BN_ULONG word = 0;
|
||||
int j;
|
||||
for (j = todo; j > 0; j--) {
|
||||
char c = in[in_len - j];
|
||||
|
||||
BN_ULONG hex;
|
||||
if (c >= '0' && c <= '9') {
|
||||
hex = c - '0';
|
||||
} else if (c >= 'a' && c <= 'f') {
|
||||
hex = c - 'a' + 10;
|
||||
} else if (c >= 'A' && c <= 'F') {
|
||||
hex = c - 'A' + 10;
|
||||
} else {
|
||||
hex = 0;
|
||||
// This shouldn't happen. The caller checks |isxdigit|.
|
||||
assert(0);
|
||||
}
|
||||
word = (word << 4) | hex;
|
||||
}
|
||||
|
||||
bn->d[i++] = word;
|
||||
in_len -= todo;
|
||||
}
|
||||
assert(i <= bn->dmax);
|
||||
bn->width = i;
|
||||
return 1;
|
||||
}
|
||||
|
||||
// decode_dec decodes |in_len| bytes of decimal data from |in| and updates |bn|.
|
||||
static int decode_dec(BIGNUM *bn, const char *in, int in_len) {
|
||||
int i, j;
|
||||
BN_ULONG l = 0;
|
||||
|
||||
// Decode |BN_DEC_NUM| digits at a time.
|
||||
j = BN_DEC_NUM - (in_len % BN_DEC_NUM);
|
||||
if (j == BN_DEC_NUM) {
|
||||
j = 0;
|
||||
}
|
||||
l = 0;
|
||||
for (i = 0; i < in_len; i++) {
|
||||
l *= 10;
|
||||
l += in[i] - '0';
|
||||
if (++j == BN_DEC_NUM) {
|
||||
if (!BN_mul_word(bn, BN_DEC_CONV) ||
|
||||
!BN_add_word(bn, l)) {
|
||||
return 0;
|
||||
}
|
||||
l = 0;
|
||||
j = 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
typedef int (*decode_func) (BIGNUM *bn, const char *in, int in_len);
|
||||
typedef int (*char_test_func) (int c);
|
||||
|
||||
static int bn_x2bn(BIGNUM **outp, const char *in, decode_func decode, char_test_func want_char) {
|
||||
BIGNUM *ret = NULL;
|
||||
int neg = 0, i;
|
||||
int num;
|
||||
|
||||
if (in == NULL || *in == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (*in == '-') {
|
||||
neg = 1;
|
||||
in++;
|
||||
}
|
||||
|
||||
for (i = 0; want_char((unsigned char)in[i]) && i + neg < INT_MAX; i++) {}
|
||||
|
||||
num = i + neg;
|
||||
if (outp == NULL) {
|
||||
return num;
|
||||
}
|
||||
|
||||
// in is the start of the hex digits, and it is 'i' long
|
||||
if (*outp == NULL) {
|
||||
ret = BN_new();
|
||||
if (ret == NULL) {
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
ret = *outp;
|
||||
BN_zero(ret);
|
||||
}
|
||||
|
||||
if (!decode(ret, in, i)) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
bn_set_minimal_width(ret);
|
||||
if (!BN_is_zero(ret)) {
|
||||
ret->neg = neg;
|
||||
}
|
||||
|
||||
*outp = ret;
|
||||
return num;
|
||||
|
||||
err:
|
||||
if (*outp == NULL) {
|
||||
BN_free(ret);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int BN_hex2bn(BIGNUM **outp, const char *in) {
|
||||
return bn_x2bn(outp, in, decode_hex, isxdigit);
|
||||
}
|
||||
|
||||
char *BN_bn2dec(const BIGNUM *a) {
|
||||
// It is easier to print strings little-endian, so we assemble it in reverse
|
||||
// and fix at the end.
|
||||
BIGNUM *copy = NULL;
|
||||
CBB cbb;
|
||||
if (!CBB_init(&cbb, 16) ||
|
||||
!CBB_add_u8(&cbb, 0 /* trailing NUL */)) {
|
||||
goto cbb_err;
|
||||
}
|
||||
|
||||
if (BN_is_zero(a)) {
|
||||
if (!CBB_add_u8(&cbb, '0')) {
|
||||
goto cbb_err;
|
||||
}
|
||||
} else {
|
||||
copy = BN_dup(a);
|
||||
if (copy == NULL) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
while (!BN_is_zero(copy)) {
|
||||
BN_ULONG word = BN_div_word(copy, BN_DEC_CONV);
|
||||
if (word == (BN_ULONG)-1) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
const int add_leading_zeros = !BN_is_zero(copy);
|
||||
for (int i = 0; i < BN_DEC_NUM && (add_leading_zeros || word != 0); i++) {
|
||||
if (!CBB_add_u8(&cbb, '0' + word % 10)) {
|
||||
goto cbb_err;
|
||||
}
|
||||
word /= 10;
|
||||
}
|
||||
assert(word == 0);
|
||||
}
|
||||
}
|
||||
|
||||
if (BN_is_negative(a) &&
|
||||
!CBB_add_u8(&cbb, '-')) {
|
||||
goto cbb_err;
|
||||
}
|
||||
|
||||
uint8_t *data;
|
||||
size_t len;
|
||||
if (!CBB_finish(&cbb, &data, &len)) {
|
||||
goto cbb_err;
|
||||
}
|
||||
|
||||
// Reverse the buffer.
|
||||
for (size_t i = 0; i < len/2; i++) {
|
||||
uint8_t tmp = data[i];
|
||||
data[i] = data[len - 1 - i];
|
||||
data[len - 1 - i] = tmp;
|
||||
}
|
||||
|
||||
BN_free(copy);
|
||||
return (char *)data;
|
||||
|
||||
cbb_err:
|
||||
OPENSSL_PUT_ERROR(BN, ERR_R_MALLOC_FAILURE);
|
||||
err:
|
||||
BN_free(copy);
|
||||
CBB_cleanup(&cbb);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int BN_dec2bn(BIGNUM **outp, const char *in) {
|
||||
return bn_x2bn(outp, in, decode_dec, isdigit);
|
||||
}
|
||||
|
||||
int BN_asc2bn(BIGNUM **outp, const char *in) {
|
||||
const char *const orig_in = in;
|
||||
if (*in == '-') {
|
||||
in++;
|
||||
}
|
||||
|
||||
if (in[0] == '0' && (in[1] == 'X' || in[1] == 'x')) {
|
||||
if (!BN_hex2bn(outp, in+2)) {
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
if (!BN_dec2bn(outp, in)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (*orig_in == '-' && !BN_is_zero(*outp)) {
|
||||
(*outp)->neg = 1;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int BN_print(BIO *bp, const BIGNUM *a) {
|
||||
int i, j, v, z = 0;
|
||||
int ret = 0;
|
||||
|
||||
if (a->neg && BIO_write(bp, "-", 1) != 1) {
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (BN_is_zero(a) && BIO_write(bp, "0", 1) != 1) {
|
||||
goto end;
|
||||
}
|
||||
|
||||
for (i = bn_minimal_width(a) - 1; i >= 0; i--) {
|
||||
for (j = BN_BITS2 - 4; j >= 0; j -= 4) {
|
||||
// strip leading zeros
|
||||
v = ((int)(a->d[i] >> (long)j)) & 0x0f;
|
||||
if (z || v != 0) {
|
||||
if (BIO_write(bp, &hextable[v], 1) != 1) {
|
||||
goto end;
|
||||
}
|
||||
z = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
ret = 1;
|
||||
|
||||
end:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int BN_print_fp(FILE *fp, const BIGNUM *a) {
|
||||
BIO *b = BIO_new_fp(fp, BIO_NOCLOSE);
|
||||
if (b == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ret = BN_print(b, a);
|
||||
BIO_free(b);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
size_t BN_bn2mpi(const BIGNUM *in, uint8_t *out) {
|
||||
const size_t bits = BN_num_bits(in);
|
||||
const size_t bytes = (bits + 7) / 8;
|
||||
// If the number of bits is a multiple of 8, i.e. if the MSB is set,
|
||||
// prefix with a zero byte.
|
||||
int extend = 0;
|
||||
if (bytes != 0 && (bits & 0x07) == 0) {
|
||||
extend = 1;
|
||||
}
|
||||
|
||||
const size_t len = bytes + extend;
|
||||
if (len < bytes ||
|
||||
4 + len < len ||
|
||||
(len & 0xffffffff) != len) {
|
||||
// If we cannot represent the number then we emit zero as the interface
|
||||
// doesn't allow an error to be signalled.
|
||||
if (out) {
|
||||
OPENSSL_memset(out, 0, 4);
|
||||
}
|
||||
return 4;
|
||||
}
|
||||
|
||||
if (out == NULL) {
|
||||
return 4 + len;
|
||||
}
|
||||
|
||||
out[0] = len >> 24;
|
||||
out[1] = len >> 16;
|
||||
out[2] = len >> 8;
|
||||
out[3] = len;
|
||||
if (extend) {
|
||||
out[4] = 0;
|
||||
}
|
||||
BN_bn2bin(in, out + 4 + extend);
|
||||
if (in->neg && len > 0) {
|
||||
out[4] |= 0x80;
|
||||
}
|
||||
return len + 4;
|
||||
}
|
||||
|
||||
BIGNUM *BN_mpi2bn(const uint8_t *in, size_t len, BIGNUM *out) {
|
||||
if (len < 4) {
|
||||
OPENSSL_PUT_ERROR(BN, BN_R_BAD_ENCODING);
|
||||
return NULL;
|
||||
}
|
||||
const size_t in_len = ((size_t)in[0] << 24) |
|
||||
((size_t)in[1] << 16) |
|
||||
((size_t)in[2] << 8) |
|
||||
((size_t)in[3]);
|
||||
if (in_len != len - 4) {
|
||||
OPENSSL_PUT_ERROR(BN, BN_R_BAD_ENCODING);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int out_is_alloced = 0;
|
||||
if (out == NULL) {
|
||||
out = BN_new();
|
||||
if (out == NULL) {
|
||||
OPENSSL_PUT_ERROR(BN, ERR_R_MALLOC_FAILURE);
|
||||
return NULL;
|
||||
}
|
||||
out_is_alloced = 1;
|
||||
}
|
||||
|
||||
if (in_len == 0) {
|
||||
BN_zero(out);
|
||||
return out;
|
||||
}
|
||||
|
||||
in += 4;
|
||||
if (BN_bin2bn(in, in_len, out) == NULL) {
|
||||
if (out_is_alloced) {
|
||||
BN_free(out);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
out->neg = ((*in) & 0x80) != 0;
|
||||
if (out->neg) {
|
||||
BN_clear_bit(out, BN_num_bits(out) - 1);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
int BN_bn2binpad(const BIGNUM *in, uint8_t *out, int len) {
|
||||
if (len < 0 ||
|
||||
!BN_bn2bin_padded(out, (size_t)len, in)) {
|
||||
return -1;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
Generated
+172
@@ -0,0 +1,172 @@
|
||||
/* Copyright (C) 1995-1998 Eric Young ([email protected])
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young (eay@cryptsoft.com).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young (eay@cryptsoft.com)"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson ([email protected])"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.] */
|
||||
|
||||
#include <openssl_grpc/buf.h>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <openssl_grpc/mem.h>
|
||||
#include <openssl_grpc/err.h>
|
||||
|
||||
#include "../internal.h"
|
||||
|
||||
|
||||
BUF_MEM *BUF_MEM_new(void) {
|
||||
BUF_MEM *ret;
|
||||
|
||||
ret = OPENSSL_malloc(sizeof(BUF_MEM));
|
||||
if (ret == NULL) {
|
||||
OPENSSL_PUT_ERROR(BUF, ERR_R_MALLOC_FAILURE);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
OPENSSL_memset(ret, 0, sizeof(BUF_MEM));
|
||||
return ret;
|
||||
}
|
||||
|
||||
void BUF_MEM_free(BUF_MEM *buf) {
|
||||
if (buf == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
OPENSSL_free(buf->data);
|
||||
OPENSSL_free(buf);
|
||||
}
|
||||
|
||||
int BUF_MEM_reserve(BUF_MEM *buf, size_t cap) {
|
||||
if (buf->max >= cap) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
size_t n = cap + 3;
|
||||
if (n < cap) {
|
||||
// overflow
|
||||
OPENSSL_PUT_ERROR(BUF, ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
n = n / 3;
|
||||
size_t alloc_size = n * 4;
|
||||
if (alloc_size / 4 != n) {
|
||||
// overflow
|
||||
OPENSSL_PUT_ERROR(BUF, ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *new_buf = OPENSSL_realloc(buf->data, alloc_size);
|
||||
if (new_buf == NULL) {
|
||||
OPENSSL_PUT_ERROR(BUF, ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
buf->data = new_buf;
|
||||
buf->max = alloc_size;
|
||||
return 1;
|
||||
}
|
||||
|
||||
size_t BUF_MEM_grow(BUF_MEM *buf, size_t len) {
|
||||
if (!BUF_MEM_reserve(buf, len)) {
|
||||
return 0;
|
||||
}
|
||||
if (buf->length < len) {
|
||||
OPENSSL_memset(&buf->data[buf->length], 0, len - buf->length);
|
||||
}
|
||||
buf->length = len;
|
||||
return len;
|
||||
}
|
||||
|
||||
size_t BUF_MEM_grow_clean(BUF_MEM *buf, size_t len) {
|
||||
return BUF_MEM_grow(buf, len);
|
||||
}
|
||||
|
||||
int BUF_MEM_append(BUF_MEM *buf, const void *in, size_t len) {
|
||||
// Work around a C language bug. See https://crbug.com/1019588.
|
||||
if (len == 0) {
|
||||
return 1;
|
||||
}
|
||||
size_t new_len = buf->length + len;
|
||||
if (new_len < len) {
|
||||
OPENSSL_PUT_ERROR(BUF, ERR_R_OVERFLOW);
|
||||
return 0;
|
||||
}
|
||||
if (!BUF_MEM_reserve(buf, new_len)) {
|
||||
return 0;
|
||||
}
|
||||
OPENSSL_memcpy(buf->data + buf->length, in, len);
|
||||
buf->length = new_len;
|
||||
return 1;
|
||||
}
|
||||
|
||||
char *BUF_strdup(const char *str) { return OPENSSL_strdup(str); }
|
||||
|
||||
size_t BUF_strnlen(const char *str, size_t max_len) {
|
||||
return OPENSSL_strnlen(str, max_len);
|
||||
}
|
||||
|
||||
char *BUF_strndup(const char *str, size_t size) {
|
||||
return OPENSSL_strndup(str, size);
|
||||
}
|
||||
|
||||
size_t BUF_strlcpy(char *dst, const char *src, size_t dst_size) {
|
||||
return OPENSSL_strlcpy(dst, src, dst_size);
|
||||
}
|
||||
|
||||
size_t BUF_strlcat(char *dst, const char *src, size_t dst_size) {
|
||||
return OPENSSL_strlcat(dst, src, dst_size);
|
||||
}
|
||||
|
||||
void *BUF_memdup(const void *data, size_t size) {
|
||||
return OPENSSL_memdup(data, size);
|
||||
}
|
||||
+172
@@ -0,0 +1,172 @@
|
||||
/* Copyright (C) 1995-1998 Eric Young ([email protected])
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young ([email protected]).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson ([email protected]).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young ([email protected])"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson ([email protected])"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.] */
|
||||
|
||||
#include <openssl/buf.h>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <openssl/mem.h>
|
||||
#include <openssl/err.h>
|
||||
|
||||
#include "../internal.h"
|
||||
|
||||
|
||||
BUF_MEM *BUF_MEM_new(void) {
|
||||
BUF_MEM *ret;
|
||||
|
||||
ret = OPENSSL_malloc(sizeof(BUF_MEM));
|
||||
if (ret == NULL) {
|
||||
OPENSSL_PUT_ERROR(BUF, ERR_R_MALLOC_FAILURE);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
OPENSSL_memset(ret, 0, sizeof(BUF_MEM));
|
||||
return ret;
|
||||
}
|
||||
|
||||
void BUF_MEM_free(BUF_MEM *buf) {
|
||||
if (buf == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
OPENSSL_free(buf->data);
|
||||
OPENSSL_free(buf);
|
||||
}
|
||||
|
||||
int BUF_MEM_reserve(BUF_MEM *buf, size_t cap) {
|
||||
if (buf->max >= cap) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
size_t n = cap + 3;
|
||||
if (n < cap) {
|
||||
// overflow
|
||||
OPENSSL_PUT_ERROR(BUF, ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
n = n / 3;
|
||||
size_t alloc_size = n * 4;
|
||||
if (alloc_size / 4 != n) {
|
||||
// overflow
|
||||
OPENSSL_PUT_ERROR(BUF, ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *new_buf = OPENSSL_realloc(buf->data, alloc_size);
|
||||
if (new_buf == NULL) {
|
||||
OPENSSL_PUT_ERROR(BUF, ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
buf->data = new_buf;
|
||||
buf->max = alloc_size;
|
||||
return 1;
|
||||
}
|
||||
|
||||
size_t BUF_MEM_grow(BUF_MEM *buf, size_t len) {
|
||||
if (!BUF_MEM_reserve(buf, len)) {
|
||||
return 0;
|
||||
}
|
||||
if (buf->length < len) {
|
||||
OPENSSL_memset(&buf->data[buf->length], 0, len - buf->length);
|
||||
}
|
||||
buf->length = len;
|
||||
return len;
|
||||
}
|
||||
|
||||
size_t BUF_MEM_grow_clean(BUF_MEM *buf, size_t len) {
|
||||
return BUF_MEM_grow(buf, len);
|
||||
}
|
||||
|
||||
int BUF_MEM_append(BUF_MEM *buf, const void *in, size_t len) {
|
||||
// Work around a C language bug. See https://crbug.com/1019588.
|
||||
if (len == 0) {
|
||||
return 1;
|
||||
}
|
||||
size_t new_len = buf->length + len;
|
||||
if (new_len < len) {
|
||||
OPENSSL_PUT_ERROR(BUF, ERR_R_OVERFLOW);
|
||||
return 0;
|
||||
}
|
||||
if (!BUF_MEM_reserve(buf, new_len)) {
|
||||
return 0;
|
||||
}
|
||||
OPENSSL_memcpy(buf->data + buf->length, in, len);
|
||||
buf->length = new_len;
|
||||
return 1;
|
||||
}
|
||||
|
||||
char *BUF_strdup(const char *str) { return OPENSSL_strdup(str); }
|
||||
|
||||
size_t BUF_strnlen(const char *str, size_t max_len) {
|
||||
return OPENSSL_strnlen(str, max_len);
|
||||
}
|
||||
|
||||
char *BUF_strndup(const char *str, size_t size) {
|
||||
return OPENSSL_strndup(str, size);
|
||||
}
|
||||
|
||||
size_t BUF_strlcpy(char *dst, const char *src, size_t dst_size) {
|
||||
return OPENSSL_strlcpy(dst, src, dst_size);
|
||||
}
|
||||
|
||||
size_t BUF_strlcat(char *dst, const char *src, size_t dst_size) {
|
||||
return OPENSSL_strlcat(dst, src, dst_size);
|
||||
}
|
||||
|
||||
void *BUF_memdup(const void *data, size_t size) {
|
||||
return OPENSSL_memdup(data, size);
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
/* Copyright (c) 2016, Google Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
||||
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
|
||||
|
||||
|
||||
#include <openssl_grpc/bytestring.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <limits.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <openssl_grpc/mem.h>
|
||||
|
||||
#include "internal.h"
|
||||
#include "../internal.h"
|
||||
|
||||
|
||||
int CBB_finish_i2d(CBB *cbb, uint8_t **outp) {
|
||||
assert(cbb->base->can_resize);
|
||||
|
||||
uint8_t *der;
|
||||
size_t der_len;
|
||||
if (!CBB_finish(cbb, &der, &der_len)) {
|
||||
CBB_cleanup(cbb);
|
||||
return -1;
|
||||
}
|
||||
if (der_len > INT_MAX) {
|
||||
OPENSSL_free(der);
|
||||
return -1;
|
||||
}
|
||||
if (outp != NULL) {
|
||||
if (*outp == NULL) {
|
||||
*outp = der;
|
||||
der = NULL;
|
||||
} else {
|
||||
OPENSSL_memcpy(*outp, der, der_len);
|
||||
*outp += der_len;
|
||||
}
|
||||
}
|
||||
OPENSSL_free(der);
|
||||
return (int)der_len;
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
/* Copyright (c) 2016, Google Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
||||
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
|
||||
|
||||
|
||||
#include <openssl/bytestring.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <limits.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <openssl/mem.h>
|
||||
|
||||
#include "internal.h"
|
||||
#include "../internal.h"
|
||||
|
||||
|
||||
int CBB_finish_i2d(CBB *cbb, uint8_t **outp) {
|
||||
assert(cbb->base->can_resize);
|
||||
|
||||
uint8_t *der;
|
||||
size_t der_len;
|
||||
if (!CBB_finish(cbb, &der, &der_len)) {
|
||||
CBB_cleanup(cbb);
|
||||
return -1;
|
||||
}
|
||||
if (der_len > INT_MAX) {
|
||||
OPENSSL_free(der);
|
||||
return -1;
|
||||
}
|
||||
if (outp != NULL) {
|
||||
if (*outp == NULL) {
|
||||
*outp = der;
|
||||
der = NULL;
|
||||
} else {
|
||||
OPENSSL_memcpy(*outp, der, der_len);
|
||||
*outp += der_len;
|
||||
}
|
||||
}
|
||||
OPENSSL_free(der);
|
||||
return (int)der_len;
|
||||
}
|
||||
+265
@@ -0,0 +1,265 @@
|
||||
/* Copyright (c) 2014, Google Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
||||
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
|
||||
|
||||
#include <openssl_grpc/bytestring.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "internal.h"
|
||||
#include "../internal.h"
|
||||
|
||||
|
||||
// kMaxDepth is a just a sanity limit. The code should be such that the length
|
||||
// of the input being processes always decreases. None the less, a very large
|
||||
// input could otherwise cause the stack to overflow.
|
||||
static const unsigned kMaxDepth = 2048;
|
||||
|
||||
// is_string_type returns one if |tag| is a string type and zero otherwise. It
|
||||
// ignores the constructed bit.
|
||||
static int is_string_type(unsigned tag) {
|
||||
switch (tag & ~CBS_ASN1_CONSTRUCTED) {
|
||||
case CBS_ASN1_BITSTRING:
|
||||
case CBS_ASN1_OCTETSTRING:
|
||||
case CBS_ASN1_UTF8STRING:
|
||||
case CBS_ASN1_NUMERICSTRING:
|
||||
case CBS_ASN1_PRINTABLESTRING:
|
||||
case CBS_ASN1_T61STRING:
|
||||
case CBS_ASN1_VIDEOTEXSTRING:
|
||||
case CBS_ASN1_IA5STRING:
|
||||
case CBS_ASN1_GRAPHICSTRING:
|
||||
case CBS_ASN1_VISIBLESTRING:
|
||||
case CBS_ASN1_GENERALSTRING:
|
||||
case CBS_ASN1_UNIVERSALSTRING:
|
||||
case CBS_ASN1_BMPSTRING:
|
||||
return 1;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// cbs_find_ber walks an ASN.1 structure in |orig_in| and sets |*ber_found|
|
||||
// depending on whether an indefinite length element or constructed string was
|
||||
// found. The value of |orig_in| is not changed. It returns one on success (i.e.
|
||||
// |*ber_found| was set) and zero on error.
|
||||
static int cbs_find_ber(const CBS *orig_in, char *ber_found, unsigned depth) {
|
||||
CBS in;
|
||||
|
||||
if (depth > kMaxDepth) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
CBS_init(&in, CBS_data(orig_in), CBS_len(orig_in));
|
||||
*ber_found = 0;
|
||||
|
||||
while (CBS_len(&in) > 0) {
|
||||
CBS contents;
|
||||
unsigned tag;
|
||||
size_t header_len;
|
||||
|
||||
if (!CBS_get_any_ber_asn1_element(&in, &contents, &tag, &header_len)) {
|
||||
return 0;
|
||||
}
|
||||
if (CBS_len(&contents) == header_len &&
|
||||
header_len > 0 &&
|
||||
CBS_data(&contents)[header_len-1] == 0x80) {
|
||||
// Found an indefinite-length element.
|
||||
*ber_found = 1;
|
||||
return 1;
|
||||
}
|
||||
if (tag & CBS_ASN1_CONSTRUCTED) {
|
||||
if (is_string_type(tag)) {
|
||||
// Constructed strings are only legal in BER and require conversion.
|
||||
*ber_found = 1;
|
||||
return 1;
|
||||
}
|
||||
if (!CBS_skip(&contents, header_len) ||
|
||||
!cbs_find_ber(&contents, ber_found, depth + 1)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
// is_eoc returns true if |header_len| and |contents|, as returned by
|
||||
// |CBS_get_any_ber_asn1_element|, indicate an "end of contents" (EOC) value.
|
||||
static char is_eoc(size_t header_len, CBS *contents) {
|
||||
return header_len == 2 && CBS_len(contents) == 2 &&
|
||||
OPENSSL_memcmp(CBS_data(contents), "\x00\x00", 2) == 0;
|
||||
}
|
||||
|
||||
// cbs_convert_ber reads BER data from |in| and writes DER data to |out|. If
|
||||
// |string_tag| is non-zero, then all elements must match |string_tag| up to the
|
||||
// constructed bit and primitive element bodies are written to |out| without
|
||||
// element headers. This is used when concatenating the fragments of a
|
||||
// constructed string. If |looking_for_eoc| is set then any EOC elements found
|
||||
// will cause the function to return after consuming it. It returns one on
|
||||
// success and zero on error.
|
||||
static int cbs_convert_ber(CBS *in, CBB *out, unsigned string_tag,
|
||||
char looking_for_eoc, unsigned depth) {
|
||||
assert(!(string_tag & CBS_ASN1_CONSTRUCTED));
|
||||
|
||||
if (depth > kMaxDepth) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
while (CBS_len(in) > 0) {
|
||||
CBS contents;
|
||||
unsigned tag, child_string_tag = string_tag;
|
||||
size_t header_len;
|
||||
CBB *out_contents, out_contents_storage;
|
||||
|
||||
if (!CBS_get_any_ber_asn1_element(in, &contents, &tag, &header_len)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (is_eoc(header_len, &contents)) {
|
||||
return looking_for_eoc;
|
||||
}
|
||||
|
||||
if (string_tag != 0) {
|
||||
// This is part of a constructed string. All elements must match
|
||||
// |string_tag| up to the constructed bit and get appended to |out|
|
||||
// without a child element.
|
||||
if ((tag & ~CBS_ASN1_CONSTRUCTED) != string_tag) {
|
||||
return 0;
|
||||
}
|
||||
out_contents = out;
|
||||
} else {
|
||||
unsigned out_tag = tag;
|
||||
if ((tag & CBS_ASN1_CONSTRUCTED) && is_string_type(tag)) {
|
||||
// If a constructed string, clear the constructed bit and inform
|
||||
// children to concatenate bodies.
|
||||
out_tag &= ~CBS_ASN1_CONSTRUCTED;
|
||||
child_string_tag = out_tag;
|
||||
}
|
||||
if (!CBB_add_asn1(out, &out_contents_storage, out_tag)) {
|
||||
return 0;
|
||||
}
|
||||
out_contents = &out_contents_storage;
|
||||
}
|
||||
|
||||
if (CBS_len(&contents) == header_len && header_len > 0 &&
|
||||
CBS_data(&contents)[header_len - 1] == 0x80) {
|
||||
// This is an indefinite length element.
|
||||
if (!cbs_convert_ber(in, out_contents, child_string_tag,
|
||||
1 /* looking for eoc */, depth + 1) ||
|
||||
!CBB_flush(out)) {
|
||||
return 0;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!CBS_skip(&contents, header_len)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (tag & CBS_ASN1_CONSTRUCTED) {
|
||||
// Recurse into children.
|
||||
if (!cbs_convert_ber(&contents, out_contents, child_string_tag,
|
||||
0 /* not looking for eoc */, depth + 1)) {
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
// Copy primitive contents as-is.
|
||||
if (!CBB_add_bytes(out_contents, CBS_data(&contents),
|
||||
CBS_len(&contents))) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (!CBB_flush(out)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return looking_for_eoc == 0;
|
||||
}
|
||||
|
||||
int CBS_asn1_ber_to_der(CBS *in, CBS *out, uint8_t **out_storage) {
|
||||
CBB cbb;
|
||||
|
||||
// First, do a quick walk to find any indefinite-length elements. Most of the
|
||||
// time we hope that there aren't any and thus we can quickly return.
|
||||
char conversion_needed;
|
||||
if (!cbs_find_ber(in, &conversion_needed, 0)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!conversion_needed) {
|
||||
if (!CBS_get_any_asn1_element(in, out, NULL, NULL)) {
|
||||
return 0;
|
||||
}
|
||||
*out_storage = NULL;
|
||||
return 1;
|
||||
}
|
||||
|
||||
size_t len;
|
||||
if (!CBB_init(&cbb, CBS_len(in)) ||
|
||||
!cbs_convert_ber(in, &cbb, 0, 0, 0) ||
|
||||
!CBB_finish(&cbb, out_storage, &len)) {
|
||||
CBB_cleanup(&cbb);
|
||||
return 0;
|
||||
}
|
||||
|
||||
CBS_init(out, *out_storage, len);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int CBS_get_asn1_implicit_string(CBS *in, CBS *out, uint8_t **out_storage,
|
||||
unsigned outer_tag, unsigned inner_tag) {
|
||||
assert(!(outer_tag & CBS_ASN1_CONSTRUCTED));
|
||||
assert(!(inner_tag & CBS_ASN1_CONSTRUCTED));
|
||||
assert(is_string_type(inner_tag));
|
||||
|
||||
if (CBS_peek_asn1_tag(in, outer_tag)) {
|
||||
// Normal implicitly-tagged string.
|
||||
*out_storage = NULL;
|
||||
return CBS_get_asn1(in, out, outer_tag);
|
||||
}
|
||||
|
||||
// Otherwise, try to parse an implicitly-tagged constructed string.
|
||||
// |CBS_asn1_ber_to_der| is assumed to have run, so only allow one level deep
|
||||
// of nesting.
|
||||
CBB result;
|
||||
CBS child;
|
||||
if (!CBB_init(&result, CBS_len(in)) ||
|
||||
!CBS_get_asn1(in, &child, outer_tag | CBS_ASN1_CONSTRUCTED)) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
while (CBS_len(&child) > 0) {
|
||||
CBS chunk;
|
||||
if (!CBS_get_asn1(&child, &chunk, inner_tag) ||
|
||||
!CBB_add_bytes(&result, CBS_data(&chunk), CBS_len(&chunk))) {
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t *data;
|
||||
size_t len;
|
||||
if (!CBB_finish(&result, &data, &len)) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
CBS_init(out, data, len);
|
||||
*out_storage = data;
|
||||
return 1;
|
||||
|
||||
err:
|
||||
CBB_cleanup(&result);
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,265 @@
|
||||
/* Copyright (c) 2014, Google Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
||||
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
|
||||
|
||||
#include <openssl/bytestring.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "internal.h"
|
||||
#include "../internal.h"
|
||||
|
||||
|
||||
// kMaxDepth is a just a sanity limit. The code should be such that the length
|
||||
// of the input being processes always decreases. None the less, a very large
|
||||
// input could otherwise cause the stack to overflow.
|
||||
static const unsigned kMaxDepth = 2048;
|
||||
|
||||
// is_string_type returns one if |tag| is a string type and zero otherwise. It
|
||||
// ignores the constructed bit.
|
||||
static int is_string_type(unsigned tag) {
|
||||
switch (tag & ~CBS_ASN1_CONSTRUCTED) {
|
||||
case CBS_ASN1_BITSTRING:
|
||||
case CBS_ASN1_OCTETSTRING:
|
||||
case CBS_ASN1_UTF8STRING:
|
||||
case CBS_ASN1_NUMERICSTRING:
|
||||
case CBS_ASN1_PRINTABLESTRING:
|
||||
case CBS_ASN1_T61STRING:
|
||||
case CBS_ASN1_VIDEOTEXSTRING:
|
||||
case CBS_ASN1_IA5STRING:
|
||||
case CBS_ASN1_GRAPHICSTRING:
|
||||
case CBS_ASN1_VISIBLESTRING:
|
||||
case CBS_ASN1_GENERALSTRING:
|
||||
case CBS_ASN1_UNIVERSALSTRING:
|
||||
case CBS_ASN1_BMPSTRING:
|
||||
return 1;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// cbs_find_ber walks an ASN.1 structure in |orig_in| and sets |*ber_found|
|
||||
// depending on whether an indefinite length element or constructed string was
|
||||
// found. The value of |orig_in| is not changed. It returns one on success (i.e.
|
||||
// |*ber_found| was set) and zero on error.
|
||||
static int cbs_find_ber(const CBS *orig_in, char *ber_found, unsigned depth) {
|
||||
CBS in;
|
||||
|
||||
if (depth > kMaxDepth) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
CBS_init(&in, CBS_data(orig_in), CBS_len(orig_in));
|
||||
*ber_found = 0;
|
||||
|
||||
while (CBS_len(&in) > 0) {
|
||||
CBS contents;
|
||||
unsigned tag;
|
||||
size_t header_len;
|
||||
|
||||
if (!CBS_get_any_ber_asn1_element(&in, &contents, &tag, &header_len)) {
|
||||
return 0;
|
||||
}
|
||||
if (CBS_len(&contents) == header_len &&
|
||||
header_len > 0 &&
|
||||
CBS_data(&contents)[header_len-1] == 0x80) {
|
||||
// Found an indefinite-length element.
|
||||
*ber_found = 1;
|
||||
return 1;
|
||||
}
|
||||
if (tag & CBS_ASN1_CONSTRUCTED) {
|
||||
if (is_string_type(tag)) {
|
||||
// Constructed strings are only legal in BER and require conversion.
|
||||
*ber_found = 1;
|
||||
return 1;
|
||||
}
|
||||
if (!CBS_skip(&contents, header_len) ||
|
||||
!cbs_find_ber(&contents, ber_found, depth + 1)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
// is_eoc returns true if |header_len| and |contents|, as returned by
|
||||
// |CBS_get_any_ber_asn1_element|, indicate an "end of contents" (EOC) value.
|
||||
static char is_eoc(size_t header_len, CBS *contents) {
|
||||
return header_len == 2 && CBS_len(contents) == 2 &&
|
||||
OPENSSL_memcmp(CBS_data(contents), "\x00\x00", 2) == 0;
|
||||
}
|
||||
|
||||
// cbs_convert_ber reads BER data from |in| and writes DER data to |out|. If
|
||||
// |string_tag| is non-zero, then all elements must match |string_tag| up to the
|
||||
// constructed bit and primitive element bodies are written to |out| without
|
||||
// element headers. This is used when concatenating the fragments of a
|
||||
// constructed string. If |looking_for_eoc| is set then any EOC elements found
|
||||
// will cause the function to return after consuming it. It returns one on
|
||||
// success and zero on error.
|
||||
static int cbs_convert_ber(CBS *in, CBB *out, unsigned string_tag,
|
||||
char looking_for_eoc, unsigned depth) {
|
||||
assert(!(string_tag & CBS_ASN1_CONSTRUCTED));
|
||||
|
||||
if (depth > kMaxDepth) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
while (CBS_len(in) > 0) {
|
||||
CBS contents;
|
||||
unsigned tag, child_string_tag = string_tag;
|
||||
size_t header_len;
|
||||
CBB *out_contents, out_contents_storage;
|
||||
|
||||
if (!CBS_get_any_ber_asn1_element(in, &contents, &tag, &header_len)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (is_eoc(header_len, &contents)) {
|
||||
return looking_for_eoc;
|
||||
}
|
||||
|
||||
if (string_tag != 0) {
|
||||
// This is part of a constructed string. All elements must match
|
||||
// |string_tag| up to the constructed bit and get appended to |out|
|
||||
// without a child element.
|
||||
if ((tag & ~CBS_ASN1_CONSTRUCTED) != string_tag) {
|
||||
return 0;
|
||||
}
|
||||
out_contents = out;
|
||||
} else {
|
||||
unsigned out_tag = tag;
|
||||
if ((tag & CBS_ASN1_CONSTRUCTED) && is_string_type(tag)) {
|
||||
// If a constructed string, clear the constructed bit and inform
|
||||
// children to concatenate bodies.
|
||||
out_tag &= ~CBS_ASN1_CONSTRUCTED;
|
||||
child_string_tag = out_tag;
|
||||
}
|
||||
if (!CBB_add_asn1(out, &out_contents_storage, out_tag)) {
|
||||
return 0;
|
||||
}
|
||||
out_contents = &out_contents_storage;
|
||||
}
|
||||
|
||||
if (CBS_len(&contents) == header_len && header_len > 0 &&
|
||||
CBS_data(&contents)[header_len - 1] == 0x80) {
|
||||
// This is an indefinite length element.
|
||||
if (!cbs_convert_ber(in, out_contents, child_string_tag,
|
||||
1 /* looking for eoc */, depth + 1) ||
|
||||
!CBB_flush(out)) {
|
||||
return 0;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!CBS_skip(&contents, header_len)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (tag & CBS_ASN1_CONSTRUCTED) {
|
||||
// Recurse into children.
|
||||
if (!cbs_convert_ber(&contents, out_contents, child_string_tag,
|
||||
0 /* not looking for eoc */, depth + 1)) {
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
// Copy primitive contents as-is.
|
||||
if (!CBB_add_bytes(out_contents, CBS_data(&contents),
|
||||
CBS_len(&contents))) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (!CBB_flush(out)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return looking_for_eoc == 0;
|
||||
}
|
||||
|
||||
int CBS_asn1_ber_to_der(CBS *in, CBS *out, uint8_t **out_storage) {
|
||||
CBB cbb;
|
||||
|
||||
// First, do a quick walk to find any indefinite-length elements. Most of the
|
||||
// time we hope that there aren't any and thus we can quickly return.
|
||||
char conversion_needed;
|
||||
if (!cbs_find_ber(in, &conversion_needed, 0)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!conversion_needed) {
|
||||
if (!CBS_get_any_asn1_element(in, out, NULL, NULL)) {
|
||||
return 0;
|
||||
}
|
||||
*out_storage = NULL;
|
||||
return 1;
|
||||
}
|
||||
|
||||
size_t len;
|
||||
if (!CBB_init(&cbb, CBS_len(in)) ||
|
||||
!cbs_convert_ber(in, &cbb, 0, 0, 0) ||
|
||||
!CBB_finish(&cbb, out_storage, &len)) {
|
||||
CBB_cleanup(&cbb);
|
||||
return 0;
|
||||
}
|
||||
|
||||
CBS_init(out, *out_storage, len);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int CBS_get_asn1_implicit_string(CBS *in, CBS *out, uint8_t **out_storage,
|
||||
unsigned outer_tag, unsigned inner_tag) {
|
||||
assert(!(outer_tag & CBS_ASN1_CONSTRUCTED));
|
||||
assert(!(inner_tag & CBS_ASN1_CONSTRUCTED));
|
||||
assert(is_string_type(inner_tag));
|
||||
|
||||
if (CBS_peek_asn1_tag(in, outer_tag)) {
|
||||
// Normal implicitly-tagged string.
|
||||
*out_storage = NULL;
|
||||
return CBS_get_asn1(in, out, outer_tag);
|
||||
}
|
||||
|
||||
// Otherwise, try to parse an implicitly-tagged constructed string.
|
||||
// |CBS_asn1_ber_to_der| is assumed to have run, so only allow one level deep
|
||||
// of nesting.
|
||||
CBB result;
|
||||
CBS child;
|
||||
if (!CBB_init(&result, CBS_len(in)) ||
|
||||
!CBS_get_asn1(in, &child, outer_tag | CBS_ASN1_CONSTRUCTED)) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
while (CBS_len(&child) > 0) {
|
||||
CBS chunk;
|
||||
if (!CBS_get_asn1(&child, &chunk, inner_tag) ||
|
||||
!CBB_add_bytes(&result, CBS_data(&chunk), CBS_len(&chunk))) {
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t *data;
|
||||
size_t len;
|
||||
if (!CBB_finish(&result, &data, &len)) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
CBS_init(out, data, len);
|
||||
*out_storage = data;
|
||||
return 1;
|
||||
|
||||
err:
|
||||
CBB_cleanup(&result);
|
||||
return 0;
|
||||
}
|
||||
+719
@@ -0,0 +1,719 @@
|
||||
/* Copyright (c) 2014, Google Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
||||
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
|
||||
|
||||
#include <openssl_grpc/bytestring.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <limits.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <openssl_grpc/mem.h>
|
||||
|
||||
#include "../internal.h"
|
||||
|
||||
|
||||
void CBB_zero(CBB *cbb) {
|
||||
OPENSSL_memset(cbb, 0, sizeof(CBB));
|
||||
}
|
||||
|
||||
static int cbb_init(CBB *cbb, uint8_t *buf, size_t cap) {
|
||||
// This assumes that |cbb| has already been zeroed.
|
||||
struct cbb_buffer_st *base;
|
||||
|
||||
base = OPENSSL_malloc(sizeof(struct cbb_buffer_st));
|
||||
if (base == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
base->buf = buf;
|
||||
base->len = 0;
|
||||
base->cap = cap;
|
||||
base->can_resize = 1;
|
||||
base->error = 0;
|
||||
|
||||
cbb->base = base;
|
||||
cbb->is_child = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int CBB_init(CBB *cbb, size_t initial_capacity) {
|
||||
CBB_zero(cbb);
|
||||
|
||||
uint8_t *buf = OPENSSL_malloc(initial_capacity);
|
||||
if (initial_capacity > 0 && buf == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!cbb_init(cbb, buf, initial_capacity)) {
|
||||
OPENSSL_free(buf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int CBB_init_fixed(CBB *cbb, uint8_t *buf, size_t len) {
|
||||
CBB_zero(cbb);
|
||||
|
||||
if (!cbb_init(cbb, buf, len)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
cbb->base->can_resize = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void CBB_cleanup(CBB *cbb) {
|
||||
// Child |CBB|s are non-owning. They are implicitly discarded and should not
|
||||
// be used with |CBB_cleanup| or |ScopedCBB|.
|
||||
assert(!cbb->is_child);
|
||||
if (cbb->is_child) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (cbb->base) {
|
||||
if (cbb->base->can_resize) {
|
||||
OPENSSL_free(cbb->base->buf);
|
||||
}
|
||||
OPENSSL_free(cbb->base);
|
||||
}
|
||||
cbb->base = NULL;
|
||||
}
|
||||
|
||||
static int cbb_buffer_reserve(struct cbb_buffer_st *base, uint8_t **out,
|
||||
size_t len) {
|
||||
size_t newlen;
|
||||
|
||||
if (base == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
newlen = base->len + len;
|
||||
if (newlen < base->len) {
|
||||
// Overflow
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (newlen > base->cap) {
|
||||
size_t newcap = base->cap * 2;
|
||||
uint8_t *newbuf;
|
||||
|
||||
if (!base->can_resize) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (newcap < base->cap || newcap < newlen) {
|
||||
newcap = newlen;
|
||||
}
|
||||
newbuf = OPENSSL_realloc(base->buf, newcap);
|
||||
if (newbuf == NULL) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
base->buf = newbuf;
|
||||
base->cap = newcap;
|
||||
}
|
||||
|
||||
if (out) {
|
||||
*out = base->buf + base->len;
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
||||
err:
|
||||
base->error = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cbb_buffer_add(struct cbb_buffer_st *base, uint8_t **out,
|
||||
size_t len) {
|
||||
if (!cbb_buffer_reserve(base, out, len)) {
|
||||
return 0;
|
||||
}
|
||||
// This will not overflow or |cbb_buffer_reserve| would have failed.
|
||||
base->len += len;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int cbb_buffer_add_u(struct cbb_buffer_st *base, uint64_t v,
|
||||
size_t len_len) {
|
||||
if (len_len == 0) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint8_t *buf;
|
||||
if (!cbb_buffer_add(base, &buf, len_len)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (size_t i = len_len - 1; i < len_len; i--) {
|
||||
buf[i] = v;
|
||||
v >>= 8;
|
||||
}
|
||||
|
||||
if (v != 0) {
|
||||
base->error = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int CBB_finish(CBB *cbb, uint8_t **out_data, size_t *out_len) {
|
||||
if (cbb->is_child) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!CBB_flush(cbb)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (cbb->base->can_resize && (out_data == NULL || out_len == NULL)) {
|
||||
// |out_data| and |out_len| can only be NULL if the CBB is fixed.
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (out_data != NULL) {
|
||||
*out_data = cbb->base->buf;
|
||||
}
|
||||
if (out_len != NULL) {
|
||||
*out_len = cbb->base->len;
|
||||
}
|
||||
cbb->base->buf = NULL;
|
||||
CBB_cleanup(cbb);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// CBB_flush recurses and then writes out any pending length prefix. The
|
||||
// current length of the underlying base is taken to be the length of the
|
||||
// length-prefixed data.
|
||||
int CBB_flush(CBB *cbb) {
|
||||
size_t child_start, i, len;
|
||||
|
||||
// If |cbb->base| has hit an error, the buffer is in an undefined state, so
|
||||
// fail all following calls. In particular, |cbb->child| may point to invalid
|
||||
// memory.
|
||||
if (cbb->base == NULL || cbb->base->error) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (cbb->child == NULL || cbb->child->pending_len_len == 0) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
child_start = cbb->child->offset + cbb->child->pending_len_len;
|
||||
|
||||
if (!CBB_flush(cbb->child) ||
|
||||
child_start < cbb->child->offset ||
|
||||
cbb->base->len < child_start) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
len = cbb->base->len - child_start;
|
||||
|
||||
if (cbb->child->pending_is_asn1) {
|
||||
// For ASN.1 we assume that we'll only need a single byte for the length.
|
||||
// If that turned out to be incorrect, we have to move the contents along
|
||||
// in order to make space.
|
||||
uint8_t len_len;
|
||||
uint8_t initial_length_byte;
|
||||
|
||||
assert (cbb->child->pending_len_len == 1);
|
||||
|
||||
if (len > 0xfffffffe) {
|
||||
// Too large.
|
||||
goto err;
|
||||
} else if (len > 0xffffff) {
|
||||
len_len = 5;
|
||||
initial_length_byte = 0x80 | 4;
|
||||
} else if (len > 0xffff) {
|
||||
len_len = 4;
|
||||
initial_length_byte = 0x80 | 3;
|
||||
} else if (len > 0xff) {
|
||||
len_len = 3;
|
||||
initial_length_byte = 0x80 | 2;
|
||||
} else if (len > 0x7f) {
|
||||
len_len = 2;
|
||||
initial_length_byte = 0x80 | 1;
|
||||
} else {
|
||||
len_len = 1;
|
||||
initial_length_byte = (uint8_t)len;
|
||||
len = 0;
|
||||
}
|
||||
|
||||
if (len_len != 1) {
|
||||
// We need to move the contents along in order to make space.
|
||||
size_t extra_bytes = len_len - 1;
|
||||
if (!cbb_buffer_add(cbb->base, NULL, extra_bytes)) {
|
||||
goto err;
|
||||
}
|
||||
OPENSSL_memmove(cbb->base->buf + child_start + extra_bytes,
|
||||
cbb->base->buf + child_start, len);
|
||||
}
|
||||
cbb->base->buf[cbb->child->offset++] = initial_length_byte;
|
||||
cbb->child->pending_len_len = len_len - 1;
|
||||
}
|
||||
|
||||
for (i = cbb->child->pending_len_len - 1; i < cbb->child->pending_len_len;
|
||||
i--) {
|
||||
cbb->base->buf[cbb->child->offset + i] = (uint8_t)len;
|
||||
len >>= 8;
|
||||
}
|
||||
if (len != 0) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
cbb->child->base = NULL;
|
||||
cbb->child = NULL;
|
||||
|
||||
return 1;
|
||||
|
||||
err:
|
||||
cbb->base->error = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
const uint8_t *CBB_data(const CBB *cbb) {
|
||||
assert(cbb->child == NULL);
|
||||
return cbb->base->buf + cbb->offset + cbb->pending_len_len;
|
||||
}
|
||||
|
||||
size_t CBB_len(const CBB *cbb) {
|
||||
assert(cbb->child == NULL);
|
||||
assert(cbb->offset + cbb->pending_len_len <= cbb->base->len);
|
||||
|
||||
return cbb->base->len - cbb->offset - cbb->pending_len_len;
|
||||
}
|
||||
|
||||
static int cbb_add_length_prefixed(CBB *cbb, CBB *out_contents,
|
||||
uint8_t len_len) {
|
||||
uint8_t *prefix_bytes;
|
||||
|
||||
if (!CBB_flush(cbb)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t offset = cbb->base->len;
|
||||
if (!cbb_buffer_add(cbb->base, &prefix_bytes, len_len)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
OPENSSL_memset(prefix_bytes, 0, len_len);
|
||||
OPENSSL_memset(out_contents, 0, sizeof(CBB));
|
||||
out_contents->base = cbb->base;
|
||||
out_contents->is_child = 1;
|
||||
cbb->child = out_contents;
|
||||
cbb->child->offset = offset;
|
||||
cbb->child->pending_len_len = len_len;
|
||||
cbb->child->pending_is_asn1 = 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int CBB_add_u8_length_prefixed(CBB *cbb, CBB *out_contents) {
|
||||
return cbb_add_length_prefixed(cbb, out_contents, 1);
|
||||
}
|
||||
|
||||
int CBB_add_u16_length_prefixed(CBB *cbb, CBB *out_contents) {
|
||||
return cbb_add_length_prefixed(cbb, out_contents, 2);
|
||||
}
|
||||
|
||||
int CBB_add_u24_length_prefixed(CBB *cbb, CBB *out_contents) {
|
||||
return cbb_add_length_prefixed(cbb, out_contents, 3);
|
||||
}
|
||||
|
||||
// add_base128_integer encodes |v| as a big-endian base-128 integer where the
|
||||
// high bit of each byte indicates where there is more data. This is the
|
||||
// encoding used in DER for both high tag number form and OID components.
|
||||
static int add_base128_integer(CBB *cbb, uint64_t v) {
|
||||
unsigned len_len = 0;
|
||||
uint64_t copy = v;
|
||||
while (copy > 0) {
|
||||
len_len++;
|
||||
copy >>= 7;
|
||||
}
|
||||
if (len_len == 0) {
|
||||
len_len = 1; // Zero is encoded with one byte.
|
||||
}
|
||||
for (unsigned i = len_len - 1; i < len_len; i--) {
|
||||
uint8_t byte = (v >> (7 * i)) & 0x7f;
|
||||
if (i != 0) {
|
||||
// The high bit denotes whether there is more data.
|
||||
byte |= 0x80;
|
||||
}
|
||||
if (!CBB_add_u8(cbb, byte)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int CBB_add_asn1(CBB *cbb, CBB *out_contents, unsigned tag) {
|
||||
if (!CBB_flush(cbb)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Split the tag into leading bits and tag number.
|
||||
uint8_t tag_bits = (tag >> CBS_ASN1_TAG_SHIFT) & 0xe0;
|
||||
unsigned tag_number = tag & CBS_ASN1_TAG_NUMBER_MASK;
|
||||
if (tag_number >= 0x1f) {
|
||||
// Set all the bits in the tag number to signal high tag number form.
|
||||
if (!CBB_add_u8(cbb, tag_bits | 0x1f) ||
|
||||
!add_base128_integer(cbb, tag_number)) {
|
||||
return 0;
|
||||
}
|
||||
} else if (!CBB_add_u8(cbb, tag_bits | tag_number)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t offset = cbb->base->len;
|
||||
if (!CBB_add_u8(cbb, 0)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
OPENSSL_memset(out_contents, 0, sizeof(CBB));
|
||||
out_contents->base = cbb->base;
|
||||
out_contents->is_child = 1;
|
||||
cbb->child = out_contents;
|
||||
cbb->child->offset = offset;
|
||||
cbb->child->pending_len_len = 1;
|
||||
cbb->child->pending_is_asn1 = 1;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int CBB_add_bytes(CBB *cbb, const uint8_t *data, size_t len) {
|
||||
uint8_t *dest;
|
||||
|
||||
if (!CBB_flush(cbb) ||
|
||||
!cbb_buffer_add(cbb->base, &dest, len)) {
|
||||
return 0;
|
||||
}
|
||||
OPENSSL_memcpy(dest, data, len);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int CBB_add_space(CBB *cbb, uint8_t **out_data, size_t len) {
|
||||
if (!CBB_flush(cbb) ||
|
||||
!cbb_buffer_add(cbb->base, out_data, len)) {
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int CBB_reserve(CBB *cbb, uint8_t **out_data, size_t len) {
|
||||
if (!CBB_flush(cbb) ||
|
||||
!cbb_buffer_reserve(cbb->base, out_data, len)) {
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int CBB_did_write(CBB *cbb, size_t len) {
|
||||
size_t newlen = cbb->base->len + len;
|
||||
if (cbb->child != NULL ||
|
||||
newlen < cbb->base->len ||
|
||||
newlen > cbb->base->cap) {
|
||||
return 0;
|
||||
}
|
||||
cbb->base->len = newlen;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int CBB_add_u8(CBB *cbb, uint8_t value) {
|
||||
if (!CBB_flush(cbb)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return cbb_buffer_add_u(cbb->base, value, 1);
|
||||
}
|
||||
|
||||
int CBB_add_u16(CBB *cbb, uint16_t value) {
|
||||
if (!CBB_flush(cbb)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return cbb_buffer_add_u(cbb->base, value, 2);
|
||||
}
|
||||
|
||||
int CBB_add_u16le(CBB *cbb, uint16_t value) {
|
||||
return CBB_add_u16(cbb, CRYPTO_bswap2(value));
|
||||
}
|
||||
|
||||
int CBB_add_u24(CBB *cbb, uint32_t value) {
|
||||
if (!CBB_flush(cbb)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return cbb_buffer_add_u(cbb->base, value, 3);
|
||||
}
|
||||
|
||||
int CBB_add_u32(CBB *cbb, uint32_t value) {
|
||||
if (!CBB_flush(cbb)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return cbb_buffer_add_u(cbb->base, value, 4);
|
||||
}
|
||||
|
||||
int CBB_add_u32le(CBB *cbb, uint32_t value) {
|
||||
return CBB_add_u32(cbb, CRYPTO_bswap4(value));
|
||||
}
|
||||
|
||||
int CBB_add_u64(CBB *cbb, uint64_t value) {
|
||||
if (!CBB_flush(cbb)) {
|
||||
return 0;
|
||||
}
|
||||
return cbb_buffer_add_u(cbb->base, value, 8);
|
||||
}
|
||||
|
||||
int CBB_add_u64le(CBB *cbb, uint64_t value) {
|
||||
return CBB_add_u64(cbb, CRYPTO_bswap8(value));
|
||||
}
|
||||
|
||||
void CBB_discard_child(CBB *cbb) {
|
||||
if (cbb->child == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
cbb->base->len = cbb->child->offset;
|
||||
|
||||
cbb->child->base = NULL;
|
||||
cbb->child = NULL;
|
||||
}
|
||||
|
||||
int CBB_add_asn1_uint64(CBB *cbb, uint64_t value) {
|
||||
CBB child;
|
||||
int started = 0;
|
||||
|
||||
if (!CBB_add_asn1(cbb, &child, CBS_ASN1_INTEGER)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < 8; i++) {
|
||||
uint8_t byte = (value >> 8*(7-i)) & 0xff;
|
||||
if (!started) {
|
||||
if (byte == 0) {
|
||||
// Don't encode leading zeros.
|
||||
continue;
|
||||
}
|
||||
// If the high bit is set, add a padding byte to make it
|
||||
// unsigned.
|
||||
if ((byte & 0x80) && !CBB_add_u8(&child, 0)) {
|
||||
return 0;
|
||||
}
|
||||
started = 1;
|
||||
}
|
||||
if (!CBB_add_u8(&child, byte)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// 0 is encoded as a single 0, not the empty string.
|
||||
if (!started && !CBB_add_u8(&child, 0)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return CBB_flush(cbb);
|
||||
}
|
||||
|
||||
int CBB_add_asn1_int64(CBB *cbb, int64_t value) {
|
||||
if (value >= 0) {
|
||||
return CBB_add_asn1_uint64(cbb, value);
|
||||
}
|
||||
|
||||
union {
|
||||
int64_t i;
|
||||
uint8_t bytes[sizeof(int64_t)];
|
||||
} u;
|
||||
u.i = value;
|
||||
int start = 7;
|
||||
// Skip leading sign-extension bytes unless they are necessary.
|
||||
while (start > 0 && (u.bytes[start] == 0xff && (u.bytes[start - 1] & 0x80))) {
|
||||
start--;
|
||||
}
|
||||
|
||||
CBB child;
|
||||
if (!CBB_add_asn1(cbb, &child, CBS_ASN1_INTEGER)) {
|
||||
return 0;
|
||||
}
|
||||
for (int i = start; i >= 0; i--) {
|
||||
if (!CBB_add_u8(&child, u.bytes[i])) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return CBB_flush(cbb);
|
||||
}
|
||||
|
||||
int CBB_add_asn1_octet_string(CBB *cbb, const uint8_t *data, size_t data_len) {
|
||||
CBB child;
|
||||
if (!CBB_add_asn1(cbb, &child, CBS_ASN1_OCTETSTRING) ||
|
||||
!CBB_add_bytes(&child, data, data_len) ||
|
||||
!CBB_flush(cbb)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int CBB_add_asn1_bool(CBB *cbb, int value) {
|
||||
CBB child;
|
||||
if (!CBB_add_asn1(cbb, &child, CBS_ASN1_BOOLEAN) ||
|
||||
!CBB_add_u8(&child, value != 0 ? 0xff : 0) ||
|
||||
!CBB_flush(cbb)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
// parse_dotted_decimal parses one decimal component from |cbs|, where |cbs| is
|
||||
// an OID literal, e.g., "1.2.840.113554.4.1.72585". It consumes both the
|
||||
// component and the dot, so |cbs| may be passed into the function again for the
|
||||
// next value.
|
||||
static int parse_dotted_decimal(CBS *cbs, uint64_t *out) {
|
||||
*out = 0;
|
||||
int seen_digit = 0;
|
||||
for (;;) {
|
||||
// Valid terminators for a component are the end of the string or a
|
||||
// non-terminal dot. If the string ends with a dot, this is not a valid OID
|
||||
// string.
|
||||
uint8_t u;
|
||||
if (!CBS_get_u8(cbs, &u) ||
|
||||
(u == '.' && CBS_len(cbs) > 0)) {
|
||||
break;
|
||||
}
|
||||
if (u < '0' || u > '9' ||
|
||||
// Forbid stray leading zeros.
|
||||
(seen_digit && *out == 0) ||
|
||||
// Check for overflow.
|
||||
*out > UINT64_MAX / 10 ||
|
||||
*out * 10 > UINT64_MAX - (u - '0')) {
|
||||
return 0;
|
||||
}
|
||||
*out = *out * 10 + (u - '0');
|
||||
seen_digit = 1;
|
||||
}
|
||||
// The empty string is not a legal OID component.
|
||||
return seen_digit;
|
||||
}
|
||||
|
||||
int CBB_add_asn1_oid_from_text(CBB *cbb, const char *text, size_t len) {
|
||||
if (!CBB_flush(cbb)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
CBS cbs;
|
||||
CBS_init(&cbs, (const uint8_t *)text, len);
|
||||
|
||||
// OIDs must have at least two components.
|
||||
uint64_t a, b;
|
||||
if (!parse_dotted_decimal(&cbs, &a) ||
|
||||
!parse_dotted_decimal(&cbs, &b)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// The first component is encoded as 40 * |a| + |b|. This assumes that |a| is
|
||||
// 0, 1, or 2 and that, when it is 0 or 1, |b| is at most 39.
|
||||
if (a > 2 ||
|
||||
(a < 2 && b > 39) ||
|
||||
b > UINT64_MAX - 80 ||
|
||||
!add_base128_integer(cbb, 40u * a + b)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// The remaining components are encoded unmodified.
|
||||
while (CBS_len(&cbs) > 0) {
|
||||
if (!parse_dotted_decimal(&cbs, &a) ||
|
||||
!add_base128_integer(cbb, a)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int compare_set_of_element(const void *a_ptr, const void *b_ptr) {
|
||||
// See X.690, section 11.6 for the ordering. They are sorted in ascending
|
||||
// order by their DER encoding.
|
||||
const CBS *a = a_ptr, *b = b_ptr;
|
||||
size_t a_len = CBS_len(a), b_len = CBS_len(b);
|
||||
size_t min_len = a_len < b_len ? a_len : b_len;
|
||||
int ret = OPENSSL_memcmp(CBS_data(a), CBS_data(b), min_len);
|
||||
if (ret != 0) {
|
||||
return ret;
|
||||
}
|
||||
if (a_len == b_len) {
|
||||
return 0;
|
||||
}
|
||||
// If one is a prefix of the other, the shorter one sorts first. (This is not
|
||||
// actually reachable. No DER encoding is a prefix of another DER encoding.)
|
||||
return a_len < b_len ? -1 : 1;
|
||||
}
|
||||
|
||||
int CBB_flush_asn1_set_of(CBB *cbb) {
|
||||
if (!CBB_flush(cbb)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
CBS cbs;
|
||||
size_t num_children = 0;
|
||||
CBS_init(&cbs, CBB_data(cbb), CBB_len(cbb));
|
||||
while (CBS_len(&cbs) != 0) {
|
||||
if (!CBS_get_any_asn1_element(&cbs, NULL, NULL, NULL)) {
|
||||
return 0;
|
||||
}
|
||||
num_children++;
|
||||
}
|
||||
|
||||
if (num_children < 2) {
|
||||
return 1; // Nothing to do. This is the common case for X.509.
|
||||
}
|
||||
if (num_children > ((size_t)-1) / sizeof(CBS)) {
|
||||
return 0; // Overflow.
|
||||
}
|
||||
|
||||
// Parse out the children and sort. We alias them into a copy of so they
|
||||
// remain valid as we rewrite |cbb|.
|
||||
int ret = 0;
|
||||
size_t buf_len = CBB_len(cbb);
|
||||
uint8_t *buf = OPENSSL_memdup(CBB_data(cbb), buf_len);
|
||||
CBS *children = OPENSSL_malloc(num_children * sizeof(CBS));
|
||||
if (buf == NULL || children == NULL) {
|
||||
goto err;
|
||||
}
|
||||
CBS_init(&cbs, buf, buf_len);
|
||||
for (size_t i = 0; i < num_children; i++) {
|
||||
if (!CBS_get_any_asn1_element(&cbs, &children[i], NULL, NULL)) {
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
qsort(children, num_children, sizeof(CBS), compare_set_of_element);
|
||||
|
||||
// Rewind |cbb| and write the contents back in the new order.
|
||||
cbb->base->len = cbb->offset + cbb->pending_len_len;
|
||||
for (size_t i = 0; i < num_children; i++) {
|
||||
if (!CBB_add_bytes(cbb, CBS_data(&children[i]), CBS_len(&children[i]))) {
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
assert(CBB_len(cbb) == buf_len);
|
||||
|
||||
ret = 1;
|
||||
|
||||
err:
|
||||
OPENSSL_free(buf);
|
||||
OPENSSL_free(children);
|
||||
return ret;
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user