Coverage Report

Created: 2022-11-30 06:20

/src/openssl/crypto/asn1/x_long.c
Line
Count
Source (jump to first uncovered line)
1
/* x_long.c */
2
/*
3
 * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
4
 * 2000.
5
 */
6
/* ====================================================================
7
 * Copyright (c) 2000 The OpenSSL Project.  All rights reserved.
8
 *
9
 * Redistribution and use in source and binary forms, with or without
10
 * modification, are permitted provided that the following conditions
11
 * are met:
12
 *
13
 * 1. Redistributions of source code must retain the above copyright
14
 *    notice, this list of conditions and the following disclaimer.
15
 *
16
 * 2. Redistributions in binary form must reproduce the above copyright
17
 *    notice, this list of conditions and the following disclaimer in
18
 *    the documentation and/or other materials provided with the
19
 *    distribution.
20
 *
21
 * 3. All advertising materials mentioning features or use of this
22
 *    software must display the following acknowledgment:
23
 *    "This product includes software developed by the OpenSSL Project
24
 *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
25
 *
26
 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
27
 *    endorse or promote products derived from this software without
28
 *    prior written permission. For written permission, please contact
29
 *    licensing@OpenSSL.org.
30
 *
31
 * 5. Products derived from this software may not be called "OpenSSL"
32
 *    nor may "OpenSSL" appear in their names without prior written
33
 *    permission of the OpenSSL Project.
34
 *
35
 * 6. Redistributions of any form whatsoever must retain the following
36
 *    acknowledgment:
37
 *    "This product includes software developed by the OpenSSL Project
38
 *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
39
 *
40
 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
41
 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
42
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
43
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
44
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
45
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
46
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
47
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
49
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
50
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
51
 * OF THE POSSIBILITY OF SUCH DAMAGE.
52
 * ====================================================================
53
 *
54
 * This product includes cryptographic software written by Eric Young
55
 * (eay@cryptsoft.com).  This product includes software written by Tim
56
 * Hudson (tjh@cryptsoft.com).
57
 *
58
 */
59
60
#include <stdio.h>
61
#include "cryptlib.h"
62
#include <openssl/asn1t.h>
63
#include <openssl/bn.h>
64
65
/*
66
 * Custom primitive type for long handling. This converts between an
67
 * ASN1_INTEGER and a long directly.
68
 */
69
70
static int long_new(ASN1_VALUE **pval, const ASN1_ITEM *it);
71
static void long_free(ASN1_VALUE **pval, const ASN1_ITEM *it);
72
73
static int long_i2c(ASN1_VALUE **pval, unsigned char *cont, int *putype,
74
                    const ASN1_ITEM *it);
75
static int long_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len,
76
                    int utype, char *free_cont, const ASN1_ITEM *it);
77
static int long_print(BIO *out, ASN1_VALUE **pval, const ASN1_ITEM *it,
78
                      int indent, const ASN1_PCTX *pctx);
79
80
static ASN1_PRIMITIVE_FUNCS long_pf = {
81
    NULL, 0,
82
    long_new,
83
    long_free,
84
    long_free,                  /* Clear should set to initial value */
85
    long_c2i,
86
    long_i2c,
87
    long_print
88
};
89
90
ASN1_ITEM_start(LONG)
91
        ASN1_ITYPE_PRIMITIVE, V_ASN1_INTEGER, NULL, 0, &long_pf, ASN1_LONG_UNDEF, "LONG"
92
ASN1_ITEM_end(LONG)
93
94
ASN1_ITEM_start(ZLONG)
95
        ASN1_ITYPE_PRIMITIVE, V_ASN1_INTEGER, NULL, 0, &long_pf, 0, "ZLONG"
96
ASN1_ITEM_end(ZLONG)
97
98
static int long_new(ASN1_VALUE **pval, const ASN1_ITEM *it)
99
0
{
100
0
    *(long *)pval = it->size;
101
0
    return 1;
102
0
}
103
104
static void long_free(ASN1_VALUE **pval, const ASN1_ITEM *it)
105
0
{
106
0
    *(long *)pval = it->size;
107
0
}
108
109
static int long_i2c(ASN1_VALUE **pval, unsigned char *cont, int *putype,
110
                    const ASN1_ITEM *it)
111
0
{
112
0
    long ltmp;
113
0
    unsigned long utmp;
114
0
    int clen, pad, i;
115
    /* this exists to bypass broken gcc optimization */
116
0
    char *cp = (char *)pval;
117
118
    /* use memcpy, because we may not be long aligned */
119
0
    memcpy(&ltmp, cp, sizeof(long));
120
121
0
    if (ltmp == it->size)
122
0
        return -1;
123
    /*
124
     * Convert the long to positive: we subtract one if negative so we can
125
     * cleanly handle the padding if only the MSB of the leading octet is
126
     * set.
127
     */
128
0
    if (ltmp < 0)
129
0
        utmp = 0 - (unsigned long)ltmp - 1;
130
0
    else
131
0
        utmp = ltmp;
132
0
    clen = BN_num_bits_word(utmp);
133
    /* If MSB of leading octet set we need to pad */
134
0
    if (!(clen & 0x7))
135
0
        pad = 1;
136
0
    else
137
0
        pad = 0;
138
139
    /* Convert number of bits to number of octets */
140
0
    clen = (clen + 7) >> 3;
141
142
0
    if (cont) {
143
0
        if (pad)
144
0
            *cont++ = (ltmp < 0) ? 0xff : 0;
145
0
        for (i = clen - 1; i >= 0; i--) {
146
0
            cont[i] = (unsigned char)(utmp & 0xff);
147
0
            if (ltmp < 0)
148
0
                cont[i] ^= 0xff;
149
0
            utmp >>= 8;
150
0
        }
151
0
    }
152
0
    return clen + pad;
153
0
}
154
155
static int long_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len,
156
                    int utype, char *free_cont, const ASN1_ITEM *it)
157
0
{
158
0
    int neg = -1, i;
159
0
    long ltmp;
160
0
    unsigned long utmp = 0;
161
0
    char *cp = (char *)pval;
162
163
0
    if (len) {
164
        /*
165
         * Check possible pad byte.  Worst case, we're skipping past actual
166
         * content, but since that's only with 0x00 and 0xff and we set neg
167
         * accordingly, the result will be correct in the end anyway.
168
         */
169
0
        switch (cont[0]) {
170
0
        case 0xff:
171
0
            cont++;
172
0
            len--;
173
0
            neg = 1;
174
0
            break;
175
0
        case 0:
176
0
            cont++;
177
0
            len--;
178
0
            neg = 0;
179
0
            break;
180
0
        }
181
0
    }
182
0
    if (len > (int)sizeof(long)) {
183
0
        ASN1err(ASN1_F_LONG_C2I, ASN1_R_INTEGER_TOO_LARGE_FOR_LONG);
184
0
        return 0;
185
0
    }
186
0
    if (neg == -1) {
187
        /* Is it negative? */
188
0
        if (len && (cont[0] & 0x80))
189
0
            neg = 1;
190
0
        else
191
0
            neg = 0;
192
0
    }
193
0
    utmp = 0;
194
0
    for (i = 0; i < len; i++) {
195
0
        utmp <<= 8;
196
0
        if (neg)
197
0
            utmp |= cont[i] ^ 0xff;
198
0
        else
199
0
            utmp |= cont[i];
200
0
    }
201
0
    ltmp = (long)utmp;
202
0
    if (neg) {
203
0
        ltmp = -ltmp;
204
0
        ltmp--;
205
0
    }
206
0
    if (ltmp == it->size) {
207
0
        ASN1err(ASN1_F_LONG_C2I, ASN1_R_INTEGER_TOO_LARGE_FOR_LONG);
208
0
        return 0;
209
0
    }
210
0
    memcpy(cp, &ltmp, sizeof(long));
211
0
    return 1;
212
0
}
213
214
static int long_print(BIO *out, ASN1_VALUE **pval, const ASN1_ITEM *it,
215
                      int indent, const ASN1_PCTX *pctx)
216
0
{
217
0
    return BIO_printf(out, "%ld\n", *(long *)pval);
218
0
}