Coverage Report

Created: 2026-04-30 06:12

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/boringssl/crypto/x509/x509_att.cc
Line
Count
Source
1
// Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
2
//
3
// Licensed under the Apache License, Version 2.0 (the "License");
4
// you may not use this file except in compliance with the License.
5
// You may obtain a copy of the License at
6
//
7
//     https://www.apache.org/licenses/LICENSE-2.0
8
//
9
// Unless required by applicable law or agreed to in writing, software
10
// distributed under the License is distributed on an "AS IS" BASIS,
11
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
// See the License for the specific language governing permissions and
13
// limitations under the License.
14
15
#include <openssl/asn1.h>
16
#include <openssl/err.h>
17
#include <openssl/obj.h>
18
#include <openssl/x509.h>
19
20
#include "../asn1/internal.h"
21
#include "internal.h"
22
23
24
using namespace bssl;
25
26
X509_ATTRIBUTE *X509_ATTRIBUTE_create_by_NID(X509_ATTRIBUTE **attr, int nid,
27
                                             int attrtype, const void *data,
28
0
                                             int len) {
29
0
  const ASN1_OBJECT *obj;
30
31
0
  obj = OBJ_nid2obj(nid);
32
0
  if (obj == nullptr) {
33
0
    OPENSSL_PUT_ERROR(X509, X509_R_UNKNOWN_NID);
34
0
    return nullptr;
35
0
  }
36
0
  return X509_ATTRIBUTE_create_by_OBJ(attr, obj, attrtype, data, len);
37
0
}
38
39
X509_ATTRIBUTE *X509_ATTRIBUTE_create_by_OBJ(X509_ATTRIBUTE **attr,
40
                                             const ASN1_OBJECT *obj,
41
                                             int attrtype, const void *data,
42
0
                                             int len) {
43
0
  X509_ATTRIBUTE *ret;
44
45
0
  if ((attr == nullptr) || (*attr == nullptr)) {
46
0
    if ((ret = X509_ATTRIBUTE_new()) == nullptr) {
47
0
      return nullptr;
48
0
    }
49
0
  } else {
50
0
    ret = *attr;
51
0
  }
52
53
0
  if (!X509_ATTRIBUTE_set1_object(ret, obj)) {
54
0
    goto err;
55
0
  }
56
0
  if (!X509_ATTRIBUTE_set1_data(ret, attrtype, data, len)) {
57
0
    goto err;
58
0
  }
59
60
0
  if ((attr != nullptr) && (*attr == nullptr)) {
61
0
    *attr = ret;
62
0
  }
63
0
  return ret;
64
0
err:
65
0
  if ((attr == nullptr) || (ret != *attr)) {
66
0
    X509_ATTRIBUTE_free(ret);
67
0
  }
68
0
  return nullptr;
69
0
}
70
71
X509_ATTRIBUTE *X509_ATTRIBUTE_create_by_txt(X509_ATTRIBUTE **attr,
72
                                             const char *attrname, int type,
73
                                             const unsigned char *bytes,
74
0
                                             int len) {
75
0
  ASN1_OBJECT *obj;
76
0
  X509_ATTRIBUTE *nattr;
77
78
0
  obj = OBJ_txt2obj(attrname, 0);
79
0
  if (obj == nullptr) {
80
0
    OPENSSL_PUT_ERROR(X509, X509_R_INVALID_FIELD_NAME);
81
0
    ERR_add_error_data(2, "name=", attrname);
82
0
    return nullptr;
83
0
  }
84
0
  nattr = X509_ATTRIBUTE_create_by_OBJ(attr, obj, type, bytes, len);
85
0
  ASN1_OBJECT_free(obj);
86
0
  return nattr;
87
0
}
88
89
0
int X509_ATTRIBUTE_set1_object(X509_ATTRIBUTE *attr, const ASN1_OBJECT *obj) {
90
0
  if ((attr == nullptr) || (obj == nullptr)) {
91
0
    return 0;
92
0
  }
93
0
  ASN1_OBJECT_free(attr->object);
94
0
  attr->object = OBJ_dup(obj);
95
0
  return attr->object != nullptr;
96
0
}
97
98
int X509_ATTRIBUTE_set1_data(X509_ATTRIBUTE *attr, int attrtype,
99
0
                             const void *data, int len) {
100
0
  if (!attr) {
101
0
    return 0;
102
0
  }
103
104
0
  if (attrtype == 0) {
105
    // Do nothing. This is used to create an empty value set in
106
    // |X509_ATTRIBUTE_create_by_*|. This is invalid, but supported by OpenSSL.
107
0
    return 1;
108
0
  }
109
110
0
  ASN1_TYPE *typ = ASN1_TYPE_new();
111
0
  if (typ == nullptr) {
112
0
    return 0;
113
0
  }
114
115
  // This function is several functions in one.
116
0
  if (attrtype & MBSTRING_FLAG) {
117
    // |data| is an encoded string. We must decode and re-encode it to |attr|'s
118
    // preferred ASN.1 type. Note |len| may be -1, in which case
119
    // |ASN1_STRING_set_by_NID| calls |strlen| automatically.
120
0
    ASN1_STRING *str =
121
0
        ASN1_STRING_set_by_NID(nullptr, reinterpret_cast<const uint8_t *>(data),
122
0
                               len, attrtype, OBJ_obj2nid(attr->object));
123
0
    if (str == nullptr) {
124
0
      OPENSSL_PUT_ERROR(X509, ERR_R_ASN1_LIB);
125
0
      goto err;
126
0
    }
127
0
    asn1_type_set0_string(typ, str);
128
0
  } else if (len != -1) {
129
    // |attrtype| must be a valid |ASN1_STRING| type. |data| and |len| is a
130
    // value in the corresponding |ASN1_STRING| representation.
131
0
    ASN1_STRING *str = ASN1_STRING_type_new(attrtype);
132
0
    if (str == nullptr || !ASN1_STRING_set(str, data, len)) {
133
0
      ASN1_STRING_free(str);
134
0
      goto err;
135
0
    }
136
0
    asn1_type_set0_string(typ, str);
137
0
  } else {
138
    // |attrtype| must be a valid |ASN1_TYPE| type. |data| is a pointer to an
139
    // object of the corresponding type.
140
0
    if (!ASN1_TYPE_set1(typ, attrtype, data)) {
141
0
      goto err;
142
0
    }
143
0
  }
144
145
0
  if (!sk_ASN1_TYPE_push(attr->set, typ)) {
146
0
    goto err;
147
0
  }
148
0
  return 1;
149
150
0
err:
151
0
  ASN1_TYPE_free(typ);
152
0
  return 0;
153
0
}
154
155
0
int X509_ATTRIBUTE_count(const X509_ATTRIBUTE *attr) {
156
0
  return (int)sk_ASN1_TYPE_num(attr->set);
157
0
}
158
159
0
ASN1_OBJECT *X509_ATTRIBUTE_get0_object(X509_ATTRIBUTE *attr) {
160
0
  if (attr == nullptr) {
161
0
    return nullptr;
162
0
  }
163
0
  return attr->object;
164
0
}
165
166
void *X509_ATTRIBUTE_get0_data(X509_ATTRIBUTE *attr, int idx, int attrtype,
167
0
                               void *unused) {
168
0
  ASN1_TYPE *ttmp;
169
0
  ttmp = X509_ATTRIBUTE_get0_type(attr, idx);
170
0
  if (!ttmp) {
171
0
    return nullptr;
172
0
  }
173
0
  if (attrtype != ASN1_TYPE_get(ttmp)) {
174
0
    OPENSSL_PUT_ERROR(X509, X509_R_WRONG_TYPE);
175
0
    return nullptr;
176
0
  }
177
0
  return (void *)asn1_type_value_as_pointer(ttmp);
178
0
}
179
180
0
ASN1_TYPE *X509_ATTRIBUTE_get0_type(X509_ATTRIBUTE *attr, int idx) {
181
0
  if (attr == nullptr) {
182
0
    return nullptr;
183
0
  }
184
0
  if (idx >= X509_ATTRIBUTE_count(attr)) {
185
0
    return nullptr;
186
0
  }
187
0
  return sk_ASN1_TYPE_value(attr->set, idx);
188
0
}