a1df06b363
return true for characters > 127. I.e. they are allowing extended ASCII characters through which then cause problems. E.g. marking superscript '2' as a number then causes the common (ch - '0') conversion to number to fail miserably. Likewise letters with diacritical marks can also cause problems. If a non-ASCII character set is being used (currently only EBCDIC), it is adjusted for. The implementation uses a single table with a bit for each of the defined classes. These functions accept an int argument and fail for values out of range or for characters outside of the ASCII set. They will work for both signed and unsigned character inputs. Reviewed-by: Andy Polyakov <appro@openssl.org> (Merged from https://github.com/openssl/openssl/pull/4102)
156 lines
3.9 KiB
C
156 lines
3.9 KiB
C
/*
|
|
* Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved.
|
|
*
|
|
* Licensed under the OpenSSL license (the "License"). You may not use
|
|
* this file except in compliance with the License. You can obtain a copy
|
|
* in the file LICENSE in the source distribution or at
|
|
* https://www.openssl.org/source/license.html
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include "internal/ctype.h"
|
|
#include "internal/cryptlib.h"
|
|
#include <openssl/buffer.h>
|
|
#include <openssl/asn1.h>
|
|
|
|
int i2a_ASN1_INTEGER(BIO *bp, const ASN1_INTEGER *a)
|
|
{
|
|
int i, n = 0;
|
|
static const char *h = "0123456789ABCDEF";
|
|
char buf[2];
|
|
|
|
if (a == NULL)
|
|
return (0);
|
|
|
|
if (a->type & V_ASN1_NEG) {
|
|
if (BIO_write(bp, "-", 1) != 1)
|
|
goto err;
|
|
n = 1;
|
|
}
|
|
|
|
if (a->length == 0) {
|
|
if (BIO_write(bp, "00", 2) != 2)
|
|
goto err;
|
|
n += 2;
|
|
} else {
|
|
for (i = 0; i < a->length; i++) {
|
|
if ((i != 0) && (i % 35 == 0)) {
|
|
if (BIO_write(bp, "\\\n", 2) != 2)
|
|
goto err;
|
|
n += 2;
|
|
}
|
|
buf[0] = h[((unsigned char)a->data[i] >> 4) & 0x0f];
|
|
buf[1] = h[((unsigned char)a->data[i]) & 0x0f];
|
|
if (BIO_write(bp, buf, 2) != 2)
|
|
goto err;
|
|
n += 2;
|
|
}
|
|
}
|
|
return (n);
|
|
err:
|
|
return (-1);
|
|
}
|
|
|
|
int a2i_ASN1_INTEGER(BIO *bp, ASN1_INTEGER *bs, char *buf, int size)
|
|
{
|
|
int i, j, k, m, n, again, bufsize;
|
|
unsigned char *s = NULL, *sp;
|
|
unsigned char *bufp;
|
|
int num = 0, slen = 0, first = 1;
|
|
|
|
bs->type = V_ASN1_INTEGER;
|
|
|
|
bufsize = BIO_gets(bp, buf, size);
|
|
for (;;) {
|
|
if (bufsize < 1)
|
|
goto err;
|
|
i = bufsize;
|
|
if (buf[i - 1] == '\n')
|
|
buf[--i] = '\0';
|
|
if (i == 0)
|
|
goto err;
|
|
if (buf[i - 1] == '\r')
|
|
buf[--i] = '\0';
|
|
if (i == 0)
|
|
goto err;
|
|
again = (buf[i - 1] == '\\');
|
|
|
|
for (j = 0; j < i; j++) {
|
|
if (!ossl_isxdigit(buf[j]))
|
|
{
|
|
i = j;
|
|
break;
|
|
}
|
|
}
|
|
buf[i] = '\0';
|
|
/*
|
|
* We have now cleared all the crap off the end of the line
|
|
*/
|
|
if (i < 2)
|
|
goto err;
|
|
|
|
bufp = (unsigned char *)buf;
|
|
if (first) {
|
|
first = 0;
|
|
if ((bufp[0] == '0') && (bufp[1] == '0')) {
|
|
bufp += 2;
|
|
i -= 2;
|
|
}
|
|
}
|
|
k = 0;
|
|
i -= again;
|
|
if (i % 2 != 0) {
|
|
ASN1err(ASN1_F_A2I_ASN1_INTEGER, ASN1_R_ODD_NUMBER_OF_CHARS);
|
|
OPENSSL_free(s);
|
|
return 0;
|
|
}
|
|
i /= 2;
|
|
if (num + i > slen) {
|
|
sp = OPENSSL_clear_realloc(s, slen, num + i * 2);
|
|
if (sp == NULL) {
|
|
ASN1err(ASN1_F_A2I_ASN1_INTEGER, ERR_R_MALLOC_FAILURE);
|
|
OPENSSL_free(s);
|
|
return 0;
|
|
}
|
|
s = sp;
|
|
slen = num + i * 2;
|
|
}
|
|
for (j = 0; j < i; j++, k += 2) {
|
|
for (n = 0; n < 2; n++) {
|
|
m = OPENSSL_hexchar2int(bufp[k + n]);
|
|
if (m < 0) {
|
|
ASN1err(ASN1_F_A2I_ASN1_INTEGER,
|
|
ASN1_R_NON_HEX_CHARACTERS);
|
|
goto err;
|
|
}
|
|
s[num + j] <<= 4;
|
|
s[num + j] |= m;
|
|
}
|
|
}
|
|
num += i;
|
|
if (again)
|
|
bufsize = BIO_gets(bp, buf, size);
|
|
else
|
|
break;
|
|
}
|
|
bs->length = num;
|
|
bs->data = s;
|
|
return 1;
|
|
err:
|
|
ASN1err(ASN1_F_A2I_ASN1_INTEGER, ASN1_R_SHORT_LINE);
|
|
OPENSSL_free(s);
|
|
return 0;
|
|
}
|
|
|
|
int i2a_ASN1_ENUMERATED(BIO *bp, const ASN1_ENUMERATED *a)
|
|
{
|
|
return i2a_ASN1_INTEGER(bp, a);
|
|
}
|
|
|
|
int a2i_ASN1_ENUMERATED(BIO *bp, ASN1_ENUMERATED *bs, char *buf, int size)
|
|
{
|
|
int rv = a2i_ASN1_INTEGER(bp, bs, buf, size);
|
|
if (rv == 1)
|
|
bs->type = V_ASN1_INTEGER | (bs->type & V_ASN1_NEG);
|
|
return rv;
|
|
}
|