1e1051a39Sopenharmony_ci/* 2e1051a39Sopenharmony_ci * Copyright 2000-2020 The OpenSSL Project Authors. All Rights Reserved. 3e1051a39Sopenharmony_ci * 4e1051a39Sopenharmony_ci * Licensed under the Apache License 2.0 (the "License"). You may not use 5e1051a39Sopenharmony_ci * this file except in compliance with the License. You can obtain a copy 6e1051a39Sopenharmony_ci * in the file LICENSE in the source distribution or at 7e1051a39Sopenharmony_ci * https://www.openssl.org/source/license.html 8e1051a39Sopenharmony_ci */ 9e1051a39Sopenharmony_ci 10e1051a39Sopenharmony_ci#include <stdio.h> 11e1051a39Sopenharmony_ci#include "internal/cryptlib.h" 12e1051a39Sopenharmony_ci#include <openssl/asn1t.h> 13e1051a39Sopenharmony_ci 14e1051a39Sopenharmony_ci#define COPY_SIZE(a, b) (sizeof(a) < sizeof(b) ? sizeof(a) : sizeof(b)) 15e1051a39Sopenharmony_ci 16e1051a39Sopenharmony_ci/* 17e1051a39Sopenharmony_ci * Custom primitive type for long handling. This converts between an 18e1051a39Sopenharmony_ci * ASN1_INTEGER and a long directly. 19e1051a39Sopenharmony_ci */ 20e1051a39Sopenharmony_ci 21e1051a39Sopenharmony_cistatic int long_new(ASN1_VALUE **pval, const ASN1_ITEM *it); 22e1051a39Sopenharmony_cistatic void long_free(ASN1_VALUE **pval, const ASN1_ITEM *it); 23e1051a39Sopenharmony_ci 24e1051a39Sopenharmony_cistatic int long_i2c(const ASN1_VALUE **pval, unsigned char *cont, int *putype, 25e1051a39Sopenharmony_ci const ASN1_ITEM *it); 26e1051a39Sopenharmony_cistatic int long_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len, 27e1051a39Sopenharmony_ci int utype, char *free_cont, const ASN1_ITEM *it); 28e1051a39Sopenharmony_cistatic int long_print(BIO *out, const ASN1_VALUE **pval, const ASN1_ITEM *it, 29e1051a39Sopenharmony_ci int indent, const ASN1_PCTX *pctx); 30e1051a39Sopenharmony_ci 31e1051a39Sopenharmony_cistatic ASN1_PRIMITIVE_FUNCS long_pf = { 32e1051a39Sopenharmony_ci NULL, 0, 33e1051a39Sopenharmony_ci long_new, 34e1051a39Sopenharmony_ci long_free, 35e1051a39Sopenharmony_ci long_free, /* Clear should set to initial value */ 36e1051a39Sopenharmony_ci long_c2i, 37e1051a39Sopenharmony_ci long_i2c, 38e1051a39Sopenharmony_ci long_print 39e1051a39Sopenharmony_ci}; 40e1051a39Sopenharmony_ci 41e1051a39Sopenharmony_ciASN1_ITEM_start(LONG) 42e1051a39Sopenharmony_ci ASN1_ITYPE_PRIMITIVE, V_ASN1_INTEGER, NULL, 0, &long_pf, ASN1_LONG_UNDEF, "LONG" 43e1051a39Sopenharmony_ciASN1_ITEM_end(LONG) 44e1051a39Sopenharmony_ci 45e1051a39Sopenharmony_ciASN1_ITEM_start(ZLONG) 46e1051a39Sopenharmony_ci ASN1_ITYPE_PRIMITIVE, V_ASN1_INTEGER, NULL, 0, &long_pf, 0, "ZLONG" 47e1051a39Sopenharmony_ciASN1_ITEM_end(ZLONG) 48e1051a39Sopenharmony_ci 49e1051a39Sopenharmony_cistatic int long_new(ASN1_VALUE **pval, const ASN1_ITEM *it) 50e1051a39Sopenharmony_ci{ 51e1051a39Sopenharmony_ci memcpy(pval, &it->size, COPY_SIZE(*pval, it->size)); 52e1051a39Sopenharmony_ci return 1; 53e1051a39Sopenharmony_ci} 54e1051a39Sopenharmony_ci 55e1051a39Sopenharmony_cistatic void long_free(ASN1_VALUE **pval, const ASN1_ITEM *it) 56e1051a39Sopenharmony_ci{ 57e1051a39Sopenharmony_ci memcpy(pval, &it->size, COPY_SIZE(*pval, it->size)); 58e1051a39Sopenharmony_ci} 59e1051a39Sopenharmony_ci 60e1051a39Sopenharmony_ci/* 61e1051a39Sopenharmony_ci * Originally BN_num_bits_word was called to perform this operation, but 62e1051a39Sopenharmony_ci * trouble is that there is no guarantee that sizeof(long) equals to 63e1051a39Sopenharmony_ci * sizeof(BN_ULONG). BN_ULONG is a configurable type that can be as wide 64e1051a39Sopenharmony_ci * as long, but also double or half... 65e1051a39Sopenharmony_ci */ 66e1051a39Sopenharmony_cistatic int num_bits_ulong(unsigned long value) 67e1051a39Sopenharmony_ci{ 68e1051a39Sopenharmony_ci size_t i; 69e1051a39Sopenharmony_ci unsigned long ret = 0; 70e1051a39Sopenharmony_ci 71e1051a39Sopenharmony_ci /* 72e1051a39Sopenharmony_ci * It is argued that *on average* constant counter loop performs 73e1051a39Sopenharmony_ci * not worse [if not better] than one with conditional break or 74e1051a39Sopenharmony_ci * mask-n-table-lookup-style, because of branch misprediction 75e1051a39Sopenharmony_ci * penalties. 76e1051a39Sopenharmony_ci */ 77e1051a39Sopenharmony_ci for (i = 0; i < sizeof(value) * 8; i++) { 78e1051a39Sopenharmony_ci ret += (value != 0); 79e1051a39Sopenharmony_ci value >>= 1; 80e1051a39Sopenharmony_ci } 81e1051a39Sopenharmony_ci 82e1051a39Sopenharmony_ci return (int)ret; 83e1051a39Sopenharmony_ci} 84e1051a39Sopenharmony_ci 85e1051a39Sopenharmony_cistatic int long_i2c(const ASN1_VALUE **pval, unsigned char *cont, int *putype, 86e1051a39Sopenharmony_ci const ASN1_ITEM *it) 87e1051a39Sopenharmony_ci{ 88e1051a39Sopenharmony_ci long ltmp; 89e1051a39Sopenharmony_ci unsigned long utmp, sign; 90e1051a39Sopenharmony_ci int clen, pad, i; 91e1051a39Sopenharmony_ci 92e1051a39Sopenharmony_ci memcpy(<mp, pval, COPY_SIZE(*pval, ltmp)); 93e1051a39Sopenharmony_ci if (ltmp == it->size) 94e1051a39Sopenharmony_ci return -1; 95e1051a39Sopenharmony_ci /* 96e1051a39Sopenharmony_ci * Convert the long to positive: we subtract one if negative so we can 97e1051a39Sopenharmony_ci * cleanly handle the padding if only the MSB of the leading octet is 98e1051a39Sopenharmony_ci * set. 99e1051a39Sopenharmony_ci */ 100e1051a39Sopenharmony_ci if (ltmp < 0) { 101e1051a39Sopenharmony_ci sign = 0xff; 102e1051a39Sopenharmony_ci utmp = 0 - (unsigned long)ltmp - 1; 103e1051a39Sopenharmony_ci } else { 104e1051a39Sopenharmony_ci sign = 0; 105e1051a39Sopenharmony_ci utmp = ltmp; 106e1051a39Sopenharmony_ci } 107e1051a39Sopenharmony_ci clen = num_bits_ulong(utmp); 108e1051a39Sopenharmony_ci /* If MSB of leading octet set we need to pad */ 109e1051a39Sopenharmony_ci if (!(clen & 0x7)) 110e1051a39Sopenharmony_ci pad = 1; 111e1051a39Sopenharmony_ci else 112e1051a39Sopenharmony_ci pad = 0; 113e1051a39Sopenharmony_ci 114e1051a39Sopenharmony_ci /* Convert number of bits to number of octets */ 115e1051a39Sopenharmony_ci clen = (clen + 7) >> 3; 116e1051a39Sopenharmony_ci 117e1051a39Sopenharmony_ci if (cont != NULL) { 118e1051a39Sopenharmony_ci if (pad) 119e1051a39Sopenharmony_ci *cont++ = (unsigned char)sign; 120e1051a39Sopenharmony_ci for (i = clen - 1; i >= 0; i--) { 121e1051a39Sopenharmony_ci cont[i] = (unsigned char)(utmp ^ sign); 122e1051a39Sopenharmony_ci utmp >>= 8; 123e1051a39Sopenharmony_ci } 124e1051a39Sopenharmony_ci } 125e1051a39Sopenharmony_ci return clen + pad; 126e1051a39Sopenharmony_ci} 127e1051a39Sopenharmony_ci 128e1051a39Sopenharmony_cistatic int long_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len, 129e1051a39Sopenharmony_ci int utype, char *free_cont, const ASN1_ITEM *it) 130e1051a39Sopenharmony_ci{ 131e1051a39Sopenharmony_ci int i; 132e1051a39Sopenharmony_ci long ltmp; 133e1051a39Sopenharmony_ci unsigned long utmp = 0, sign = 0x100; 134e1051a39Sopenharmony_ci 135e1051a39Sopenharmony_ci if (len > 1) { 136e1051a39Sopenharmony_ci /* 137e1051a39Sopenharmony_ci * Check possible pad byte. Worst case, we're skipping past actual 138e1051a39Sopenharmony_ci * content, but since that's only with 0x00 and 0xff and we set neg 139e1051a39Sopenharmony_ci * accordingly, the result will be correct in the end anyway. 140e1051a39Sopenharmony_ci */ 141e1051a39Sopenharmony_ci switch (cont[0]) { 142e1051a39Sopenharmony_ci case 0xff: 143e1051a39Sopenharmony_ci cont++; 144e1051a39Sopenharmony_ci len--; 145e1051a39Sopenharmony_ci sign = 0xff; 146e1051a39Sopenharmony_ci break; 147e1051a39Sopenharmony_ci case 0: 148e1051a39Sopenharmony_ci cont++; 149e1051a39Sopenharmony_ci len--; 150e1051a39Sopenharmony_ci sign = 0; 151e1051a39Sopenharmony_ci break; 152e1051a39Sopenharmony_ci } 153e1051a39Sopenharmony_ci } 154e1051a39Sopenharmony_ci if (len > (int)sizeof(long)) { 155e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_ASN1, ASN1_R_INTEGER_TOO_LARGE_FOR_LONG); 156e1051a39Sopenharmony_ci return 0; 157e1051a39Sopenharmony_ci } 158e1051a39Sopenharmony_ci 159e1051a39Sopenharmony_ci if (sign == 0x100) { 160e1051a39Sopenharmony_ci /* Is it negative? */ 161e1051a39Sopenharmony_ci if (len && (cont[0] & 0x80)) 162e1051a39Sopenharmony_ci sign = 0xff; 163e1051a39Sopenharmony_ci else 164e1051a39Sopenharmony_ci sign = 0; 165e1051a39Sopenharmony_ci } else if (((sign ^ cont[0]) & 0x80) == 0) { /* same sign bit? */ 166e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_ASN1, ASN1_R_ILLEGAL_PADDING); 167e1051a39Sopenharmony_ci return 0; 168e1051a39Sopenharmony_ci } 169e1051a39Sopenharmony_ci utmp = 0; 170e1051a39Sopenharmony_ci for (i = 0; i < len; i++) { 171e1051a39Sopenharmony_ci utmp <<= 8; 172e1051a39Sopenharmony_ci utmp |= cont[i] ^ sign; 173e1051a39Sopenharmony_ci } 174e1051a39Sopenharmony_ci ltmp = (long)utmp; 175e1051a39Sopenharmony_ci if (ltmp < 0) { 176e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_ASN1, ASN1_R_INTEGER_TOO_LARGE_FOR_LONG); 177e1051a39Sopenharmony_ci return 0; 178e1051a39Sopenharmony_ci } 179e1051a39Sopenharmony_ci if (sign) 180e1051a39Sopenharmony_ci ltmp = -ltmp - 1; 181e1051a39Sopenharmony_ci if (ltmp == it->size) { 182e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_ASN1, ASN1_R_INTEGER_TOO_LARGE_FOR_LONG); 183e1051a39Sopenharmony_ci return 0; 184e1051a39Sopenharmony_ci } 185e1051a39Sopenharmony_ci memcpy(pval, <mp, COPY_SIZE(*pval, ltmp)); 186e1051a39Sopenharmony_ci return 1; 187e1051a39Sopenharmony_ci} 188e1051a39Sopenharmony_ci 189e1051a39Sopenharmony_cistatic int long_print(BIO *out, const ASN1_VALUE **pval, const ASN1_ITEM *it, 190e1051a39Sopenharmony_ci int indent, const ASN1_PCTX *pctx) 191e1051a39Sopenharmony_ci{ 192e1051a39Sopenharmony_ci long l; 193e1051a39Sopenharmony_ci 194e1051a39Sopenharmony_ci memcpy(&l, pval, COPY_SIZE(*pval, l)); 195e1051a39Sopenharmony_ci return BIO_printf(out, "%ld\n", l); 196e1051a39Sopenharmony_ci} 197