/* This will write the AttributeTypeAndValue field. The data must be already DER encoded. * 'multi' must be (0) if writing an AttributeTypeAndValue, and 1 if Attribute. * In all cases only one value is written. */ static int _gnutls_x509_write_attribute(const char *given_oid, ASN1_TYPE asn1_struct, const char *where, const void *_data, int sizeof_data) { char tmp[128]; int result; /* write the data (value) */ _gnutls_str_cpy(tmp, sizeof(tmp), where); _gnutls_str_cat(tmp, sizeof(tmp), ".value"); result = asn1_write_value(asn1_struct, tmp, _data, sizeof_data); if (result < 0) { gnutls_assert(); return _gnutls_asn2err(result); } /* write the type */ _gnutls_str_cpy(tmp, sizeof(tmp), where); _gnutls_str_cat(tmp, sizeof(tmp), ".type"); result = asn1_write_value(asn1_struct, tmp, given_oid, 1); if (result != ASN1_SUCCESS) { gnutls_assert(); return _gnutls_asn2err(result); } return 0; }
int _gnutls_write_new_general_name(ASN1_TYPE ext, const char *ext_name, gnutls_x509_subject_alt_name_t type, const void *data, unsigned int data_size) { int result; char name[128]; result = asn1_write_value(ext, ext_name, "NEW", 1); if (result != ASN1_SUCCESS) { gnutls_assert(); return _gnutls_asn2err(result); } if (ext_name[0] == 0) { /* no dot */ _gnutls_str_cpy(name, sizeof(name), "?LAST"); } else { _gnutls_str_cpy(name, sizeof(name), ext_name); _gnutls_str_cat(name, sizeof(name), ".?LAST"); } result = _gnutls_write_general_name(ext, name, type, data, data_size); if (result < 0) { gnutls_assert(); return result; } return 0; }
static int write_new_general_name(ASN1_TYPE ext, const char *ext_name, gnutls_x509_subject_alt_name_t type, const void *data, unsigned int data_size) { const char *str; int result; char name[128]; result = asn1_write_value(ext, ext_name, "NEW", 1); if (result != ASN1_SUCCESS) { gnutls_assert(); return _gnutls_asn2err(result); } switch (type) { case GNUTLS_SAN_DNSNAME: str = "dNSName"; break; case GNUTLS_SAN_RFC822NAME: str = "rfc822Name"; break; case GNUTLS_SAN_URI: str = "uniformResourceIdentifier"; break; case GNUTLS_SAN_IPADDRESS: str = "iPAddress"; break; default: gnutls_assert(); return GNUTLS_E_INTERNAL_ERROR; } if (ext_name[0] == 0) { /* no dot */ _gnutls_str_cpy(name, sizeof(name), "?LAST"); } else { _gnutls_str_cpy(name, sizeof(name), ext_name); _gnutls_str_cat(name, sizeof(name), ".?LAST"); } result = asn1_write_value(ext, name, str, 1); if (result != ASN1_SUCCESS) { gnutls_assert(); return _gnutls_asn2err(result); } _gnutls_str_cat(name, sizeof(name), "."); _gnutls_str_cat(name, sizeof(name), str); result = asn1_write_value(ext, name, data, data_size); if (result != ASN1_SUCCESS) { gnutls_assert(); asn1_delete_structure(&ext); return _gnutls_asn2err(result); } return 0; }
void _asnstr_append_name(char *name, size_t name_size, const char *part1, const char *part2) { if (part1[0] != 0) { _gnutls_str_cpy(name, name_size, part1); _gnutls_str_cat(name, name_size, part2); } else _gnutls_str_cpy(name, name_size, part2 + 1 /* remove initial dot */ ); }
/* Decodes an octet string. Leave string_type null for a normal * octet string. Otherwise put something like BMPString, PrintableString * etc. */ int _gnutls_x509_decode_octet_string (const char *string_type, const opaque * der, size_t der_size, opaque * output, size_t * output_size) { ASN1_TYPE c2 = ASN1_TYPE_EMPTY; int result, tmp_output_size; char strname[64]; if (string_type == NULL) _gnutls_str_cpy (strname, sizeof (strname), "PKIX1.pkcs-7-Data"); else { _gnutls_str_cpy (strname, sizeof (strname), "PKIX1."); _gnutls_str_cat (strname, sizeof (strname), string_type); } if ((result = asn1_create_element (_gnutls_get_pkix (), strname, &c2)) != ASN1_SUCCESS) { gnutls_assert (); result = _gnutls_asn2err (result); goto cleanup; } result = asn1_der_decoding (&c2, der, der_size, NULL); if (result != ASN1_SUCCESS) { gnutls_assert (); result = _gnutls_asn2err (result); goto cleanup; } tmp_output_size = *output_size; result = asn1_read_value (c2, "", output, &tmp_output_size); *output_size = tmp_output_size; if (result != ASN1_SUCCESS) { gnutls_assert (); result = _gnutls_asn2err (result); goto cleanup; } result = 0; cleanup: if (c2) asn1_delete_structure (&c2); return result; }
/* * This function writes and encodes the parameters for DSS or RSA keys. * This is the "signatureAlgorithm" fields. */ int _gnutls_x509_write_sig_params (ASN1_TYPE dst, const char *dst_name, gnutls_pk_algorithm_t pk_algorithm, gnutls_digest_algorithm_t dig) { int result; char name[128]; const char *pk; _gnutls_str_cpy (name, sizeof (name), dst_name); _gnutls_str_cat (name, sizeof (name), ".algorithm"); pk = _gnutls_x509_sign_to_oid (pk_algorithm, HASH2MAC (dig)); if (pk == NULL) { gnutls_assert (); _gnutls_debug_log ("Cannot find OID for sign algorithm pk: %d dig: %d\n", (int) pk_algorithm, (int) dig); return GNUTLS_E_INVALID_REQUEST; } /* write the OID. */ result = asn1_write_value (dst, name, pk, 1); if (result != ASN1_SUCCESS) { gnutls_assert (); return _gnutls_asn2err (result); } _gnutls_str_cpy (name, sizeof (name), dst_name); _gnutls_str_cat (name, sizeof (name), ".parameters"); if (pk_algorithm == GNUTLS_PK_RSA) result = asn1_write_value (dst, name, ASN1_NULL, ASN1_NULL_SIZE); else result = asn1_write_value (dst, name, NULL, 0); if (result != ASN1_SUCCESS && result != ASN1_ELEMENT_NOT_FOUND) { /* Here we ignore the element not found error, since this * may have been disabled before. */ gnutls_assert (); return _gnutls_asn2err (result); } return 0; }
/* This will write the AttributeTypeAndValue field. The data must be already DER encoded. * 'multi' must be zero if writing an AttributeTypeAndValue, and 1 if Attribute. * In all cases only one value is written. */ int _gnutls_x509_write_attribute (const char *given_oid, ASN1_TYPE asn1_struct, const char *where, const void *_data, int sizeof_data, int multi) { char tmp[128]; int result; /* write the data (value) */ _gnutls_str_cpy (tmp, sizeof (tmp), where); _gnutls_str_cat (tmp, sizeof (tmp), ".value"); if (multi != 0) { /* if not writing an AttributeTypeAndValue, but an Attribute */ _gnutls_str_cat (tmp, sizeof (tmp), "s"); /* values */ result = asn1_write_value (asn1_struct, tmp, "NEW", 1); if (result != ASN1_SUCCESS) { gnutls_assert (); return _gnutls_asn2err (result); } _gnutls_str_cat (tmp, sizeof (tmp), ".?LAST"); } result = asn1_write_value (asn1_struct, tmp, _data, sizeof_data); if (result < 0) { gnutls_assert (); return _gnutls_asn2err (result); } /* write the type */ _gnutls_str_cpy (tmp, sizeof (tmp), where); _gnutls_str_cat (tmp, sizeof (tmp), ".type"); result = asn1_write_value (asn1_struct, tmp, given_oid, 1); if (result != ASN1_SUCCESS) { gnutls_assert (); return _gnutls_asn2err (result); } return 0; }
/* Decodes an X.509 Attribute (if multi==1) or an AttributeTypeAndValue * otherwise. * * octet_string should be non-zero if we are to decode octet strings after * decoding. * * The output is allocated and stored in value. */ int _gnutls_x509_decode_and_read_attribute(ASN1_TYPE asn1_struct, const char *where, char *oid, int oid_size, gnutls_datum_t * value, int multi, int octet_string) { char tmpbuffer[128]; int len, result; /* Read the OID */ _gnutls_str_cpy(tmpbuffer, sizeof(tmpbuffer), where); _gnutls_str_cat(tmpbuffer, sizeof(tmpbuffer), ".type"); len = oid_size - 1; result = asn1_read_value(asn1_struct, tmpbuffer, oid, &len); if (result != ASN1_SUCCESS) { gnutls_assert(); result = _gnutls_asn2err(result); return result; } /* Read the Value */ _gnutls_str_cpy(tmpbuffer, sizeof(tmpbuffer), where); _gnutls_str_cat(tmpbuffer, sizeof(tmpbuffer), ".value"); if (multi) _gnutls_str_cat(tmpbuffer, sizeof(tmpbuffer), "s.?1"); /* .values.?1 */ if (octet_string) result = _gnutls_x509_read_string(asn1_struct, tmpbuffer, value, ASN1_ETYPE_OCTET_STRING, 0); else result = _gnutls_x509_read_value(asn1_struct, tmpbuffer, value); if (result < 0) { gnutls_assert(); return result; } return 0; }
/* Sets the time in time_t in the ASN1_TYPE given. Where should * be something like "tbsCertList.thisUpdate". */ int _gnutls_x509_set_time (ASN1_TYPE c2, const char *where, time_t tim) { char str_time[MAX_TIME]; char name[128]; int result, len; _gnutls_str_cpy (name, sizeof (name), where); if ((result = asn1_write_value (c2, name, "utcTime", 1)) < 0) { gnutls_assert (); return _gnutls_asn2err (result); } result = _gnutls_x509_gtime2utcTime (tim, str_time, sizeof (str_time)); if (result < 0) { gnutls_assert (); return result; } _gnutls_str_cat (name, sizeof (name), ".utcTime"); len = strlen (str_time); result = asn1_write_value (c2, name, str_time, len); if (result != ASN1_SUCCESS) { gnutls_assert (); return _gnutls_asn2err (result); } return 0; }
/* This function will attempt to return the requested extension OID found in * the given X509v3 certificate. * * If you have passed the last extension, GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE will * be returned. */ static int get_extension_oid(ASN1_TYPE asn, const char *root, unsigned indx, void *oid, size_t * sizeof_oid) { int k, result, len; char name[ASN1_MAX_NAME_SIZE], name2[ASN1_MAX_NAME_SIZE]; char extnID[MAX_OID_SIZE]; unsigned indx_counter = 0; k = 0; do { k++; snprintf(name, sizeof(name), "%s.?%u", root, k); _gnutls_str_cpy(name2, sizeof(name2), name); _gnutls_str_cat(name2, sizeof(name2), ".extnID"); len = sizeof(extnID) - 1; result = asn1_read_value(asn, name2, extnID, &len); if (result == ASN1_ELEMENT_NOT_FOUND) { gnutls_assert(); break; } else if (result != ASN1_SUCCESS) { gnutls_assert(); return _gnutls_asn2err(result); } /* Handle Extension */ if (indx == indx_counter++) { len = strlen(extnID) + 1; if (*sizeof_oid < (unsigned) len) { *sizeof_oid = len; gnutls_assert(); return GNUTLS_E_SHORT_MEMORY_BUFFER; } memcpy(oid, extnID, len); *sizeof_oid = len - 1; return 0; } } while (1); if (result == ASN1_ELEMENT_NOT_FOUND) { return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; } else { gnutls_assert(); return _gnutls_asn2err(result); } }
/* Overwrite the given extension (using the index) * index here starts from one. */ static int overwrite_extension (ASN1_TYPE asn, const char *root, unsigned int indx, const gnutls_datum_t * ext_data, unsigned int critical) { char name[ASN1_MAX_NAME_SIZE], name2[ASN1_MAX_NAME_SIZE]; const char *str; int result; if (root[0] != 0) snprintf (name, sizeof (name), "%s.?%u", root, indx); else snprintf (name, sizeof (name), "?%u", indx); if (critical == 0) str = "FALSE"; else str = "TRUE"; _gnutls_str_cpy (name2, sizeof (name2), name); _gnutls_str_cat (name2, sizeof (name2), ".critical"); result = asn1_write_value (asn, name2, str, 1); if (result != ASN1_SUCCESS) { gnutls_assert (); return _gnutls_asn2err (result); } _gnutls_str_cpy (name2, sizeof (name2), name); _gnutls_str_cat (name2, sizeof (name2), ".extnValue"); result = _gnutls_x509_write_value (asn, name2, ext_data); if (result < 0) { gnutls_assert (); return result; } return 0; }
time_t _gnutls_x509_get_time (ASN1_TYPE c2, const char *when) { char ttime[MAX_TIME]; char name[128]; time_t c_time = (time_t) - 1; int len, result; _gnutls_str_cpy (name, sizeof (name), when); len = sizeof (ttime) - 1; if ((result = asn1_read_value (c2, name, ttime, &len)) < 0) { gnutls_assert (); return (time_t) (-1); } /* CHOICE */ if (strcmp (ttime, "generalTime") == 0) { _gnutls_str_cat (name, sizeof (name), ".generalTime"); len = sizeof (ttime) - 1; result = asn1_read_value (c2, name, ttime, &len); if (result == ASN1_SUCCESS) c_time = _gnutls_x509_generalTime2gtime (ttime); } else { /* UTCTIME */ _gnutls_str_cat (name, sizeof (name), ".utcTime"); len = sizeof (ttime) - 1; result = asn1_read_value (c2, name, ttime, &len); if (result == ASN1_SUCCESS) c_time = _gnutls_x509_utcTime2gtime (ttime); } /* We cannot handle dates after 2031 in 32 bit machines. * a time_t of 64bits has to be used. */ if (result != ASN1_SUCCESS) { gnutls_assert (); return (time_t) (-1); } return c_time; }
/* Sets the time in time_t in the ASN1_TYPE given. Where should * be something like "tbsCertList.thisUpdate". */ int _gnutls_x509_set_time(ASN1_TYPE c2, const char *where, time_t tim, int nochoice) { char str_time[MAX_TIME]; char name[128]; int result, len; if (nochoice != 0) { result = gtime2generalTime(tim, str_time, sizeof(str_time)); if (result < 0) return gnutls_assert_val(result); len = strlen(str_time); result = asn1_write_value(c2, where, str_time, len); if (result != ASN1_SUCCESS) return gnutls_assert_val(_gnutls_asn2err(result)); return 0; } _gnutls_str_cpy(name, sizeof(name), where); if ((result = asn1_write_value(c2, name, "generalTime", 1)) < 0) { gnutls_assert(); return _gnutls_asn2err(result); } result = gtime2generalTime(tim, str_time, sizeof(str_time)); if (result < 0) { gnutls_assert(); return result; } _gnutls_str_cat(name, sizeof(name), ".generalTime"); len = strlen(str_time); result = asn1_write_value(c2, name, str_time, len); if (result != ASN1_SUCCESS) { gnutls_assert(); return _gnutls_asn2err(result); } return 0; }
int _gnutls_fbase64_decode (const char *header, const uint8_t * data, size_t data_size, gnutls_datum_t* result) { int ret; static const char top[] = "-----BEGIN "; static const char bottom[] = "-----END "; uint8_t *rdata, *kdata; int rdata_size; char pem_header[128]; _gnutls_str_cpy (pem_header, sizeof (pem_header), top); if (header != NULL) _gnutls_str_cat (pem_header, sizeof (pem_header), header); rdata = memmem (data, data_size, pem_header, strlen (pem_header)); if (rdata == NULL) { gnutls_assert (); _gnutls_debug_log ("Could not find '%s'\n", pem_header); return GNUTLS_E_BASE64_UNEXPECTED_HEADER_ERROR; } data_size -= (unsigned long int) rdata - (unsigned long int) data; if (data_size < 4 + strlen (bottom)) { gnutls_assert (); return GNUTLS_E_BASE64_DECODING_ERROR; } kdata = memmem (rdata + 1, data_size - 1, ENDSTR, sizeof (ENDSTR) - 1); /* allow CR as well. */ if (kdata == NULL) { gnutls_assert (); _gnutls_debug_log ("Could not find '%s'\n", ENDSTR); return GNUTLS_E_BASE64_DECODING_ERROR; } data_size -= strlen (ENDSTR); data_size -= (unsigned long int) kdata - (unsigned long int) rdata; rdata = kdata + strlen (ENDSTR); /* position is now after the ---BEGIN--- headers */ kdata = memmem (rdata, data_size, bottom, strlen (bottom)); if (kdata == NULL) { gnutls_assert (); return GNUTLS_E_BASE64_DECODING_ERROR; } /* position of kdata is before the ----END--- footer */ rdata_size = (unsigned long int) kdata - (unsigned long int) rdata; if (rdata_size < 4) { gnutls_assert (); return GNUTLS_E_BASE64_DECODING_ERROR; } if ((ret = _gnutls_base64_decode (rdata, rdata_size, result)) < 0) { gnutls_assert (); return GNUTLS_E_BASE64_DECODING_ERROR; } return ret; }
/* encodes data and puts the result into result (locally allocated) * The result_size (including the null terminator) is the return value. */ int _gnutls_fbase64_encode (const char *msg, const uint8_t * data, size_t data_size, gnutls_datum_t * result) { int tmp; unsigned int i; char tmpres[66]; uint8_t *ptr; char top[80]; char bottom[80]; size_t size, max, bytes; int pos, top_len, bottom_len; if (msg == NULL || strlen(msg) > 50) { gnutls_assert (); return GNUTLS_E_BASE64_ENCODING_ERROR; } _gnutls_str_cpy (top, sizeof(top), "-----BEGIN "); _gnutls_str_cat (top, sizeof(top), msg); _gnutls_str_cat (top, sizeof(top), "-----\n"); _gnutls_str_cpy (bottom, sizeof(bottom), "-----END "); _gnutls_str_cat (bottom, sizeof(bottom), msg); _gnutls_str_cat (bottom, sizeof(bottom), "-----\n"); top_len = strlen (top); bottom_len = strlen (bottom); max = B64FSIZE (top_len+bottom_len, data_size); result->data = gnutls_malloc (max + 1); if (result->data == NULL) { gnutls_assert (); return GNUTLS_E_MEMORY_ERROR; } bytes = pos = 0; INCR (bytes, top_len, max); pos = top_len; memcpy (result->data, top, top_len); for (i = 0; i < data_size; i += 48) { if (data_size - i < 48) tmp = data_size - i; else tmp = 48; base64_encode ((void*)&data[i], tmp, tmpres, sizeof(tmpres)); size = strlen(tmpres); INCR (bytes, size+1, max); ptr = &result->data[pos]; memcpy(ptr, tmpres, size); ptr += size; *ptr++ = '\n'; pos += size + 1; } INCR (bytes, bottom_len, max); memcpy (&result->data[bytes - bottom_len], bottom, bottom_len); result->data[bytes] = 0; result->size = bytes; return max + 1; }
/* Parses an X509 DN in the asn1_struct, and searches for the * given OID in the DN. * * If raw_flag == 0, the output will be encoded in the LDAP way. (#hex for non printable) * Otherwise the raw DER data are returned. * * asn1_rdn_name must be a string in the form "tbsCertificate.issuer.rdnSequence". * That is to point in the rndSequence. * * indx specifies which OID to return. Ie 0 means return the first specified * OID found, 1 the second etc. */ int _gnutls_x509_parse_dn_oid(ASN1_TYPE asn1_struct, const char *asn1_rdn_name, const char *given_oid, int indx, unsigned int raw_flag, gnutls_datum_t * out) { int k2, k1, result; char tmpbuffer1[ASN1_MAX_NAME_SIZE]; char tmpbuffer2[ASN1_MAX_NAME_SIZE]; char tmpbuffer3[ASN1_MAX_NAME_SIZE]; gnutls_datum_t td; uint8_t value[256]; char oid[MAX_OID_SIZE]; int len; int i = 0; k1 = 0; do { k1++; /* create a string like "tbsCertList.issuer.rdnSequence.?1" */ if (asn1_rdn_name[0] != 0) snprintf(tmpbuffer1, sizeof(tmpbuffer1), "%s.?%u", asn1_rdn_name, k1); else snprintf(tmpbuffer1, sizeof(tmpbuffer1), "?%u", k1); len = sizeof(value) - 1; result = asn1_read_value(asn1_struct, tmpbuffer1, value, &len); if (result == ASN1_ELEMENT_NOT_FOUND) { gnutls_assert(); break; } if (result != ASN1_VALUE_NOT_FOUND) { gnutls_assert(); result = _gnutls_asn2err(result); goto cleanup; } k2 = 0; do { /* Move to the attibute type and values */ k2++; if (tmpbuffer1[0] != 0) snprintf(tmpbuffer2, sizeof(tmpbuffer2), "%s.?%u", tmpbuffer1, k2); else snprintf(tmpbuffer2, sizeof(tmpbuffer2), "?%u", k2); /* Try to read the RelativeDistinguishedName attributes. */ len = sizeof(value) - 1; result = asn1_read_value(asn1_struct, tmpbuffer2, value, &len); if (result == ASN1_ELEMENT_NOT_FOUND) { break; } if (result != ASN1_VALUE_NOT_FOUND) { gnutls_assert(); result = _gnutls_asn2err(result); goto cleanup; } /* Read the OID */ _gnutls_str_cpy(tmpbuffer3, sizeof(tmpbuffer3), tmpbuffer2); _gnutls_str_cat(tmpbuffer3, sizeof(tmpbuffer3), ".type"); len = sizeof(oid) - 1; result = asn1_read_value(asn1_struct, tmpbuffer3, oid, &len); if (result == ASN1_ELEMENT_NOT_FOUND) break; else if (result != ASN1_SUCCESS) { gnutls_assert(); result = _gnutls_asn2err(result); goto cleanup; } if (strcmp(oid, given_oid) == 0 && indx == i++) { /* Found the OID */ /* Read the Value */ _gnutls_str_cpy(tmpbuffer3, sizeof(tmpbuffer3), tmpbuffer2); _gnutls_str_cat(tmpbuffer3, sizeof(tmpbuffer3), ".value"); result = _gnutls_x509_read_value(asn1_struct, tmpbuffer3, &td); if (result < 0) { gnutls_assert(); goto cleanup; } if (raw_flag != 0) { out->data = td.data; out->size = td.size; return 0; } else { /* parse data. raw_flag == 0 */ result = _gnutls_x509_dn_to_string(oid, td. data, td. size, out); _gnutls_free_datum(&td); if (result < 0) { gnutls_assert(); goto cleanup; } return 0; } /* raw_flag == 0 */ } } while (1); } while (1); gnutls_assert(); result = GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; cleanup: return result; }
/* Send the first key exchange message ( g, n, s) and append the verifier algorithm number * Data is allocated by the caller, and should have data_size size. */ int _gnutls_gen_srp_server_kx (gnutls_session_t session, opaque ** data) { int ret; uint8_t *data_n, *data_s; uint8_t *data_g; char *username; SRP_PWD_ENTRY *pwd_entry; srp_server_auth_info_t info; ssize_t data_size; size_t n_b, tmp_size; char buf[64]; uint8_t *data_b; if ((ret = _gnutls_auth_info_set (session, GNUTLS_CRD_SRP, sizeof (srp_server_auth_info_st), 1)) < 0) { gnutls_assert (); return ret; } info = _gnutls_get_auth_info (session); username = info->username; _gnutls_str_cpy (username, MAX_SRP_USERNAME, session->security_parameters.extensions.srp_username); ret = _gnutls_srp_pwd_read_entry (session, username, &pwd_entry); if (ret < 0) { gnutls_assert (); return ret; } /* copy from pwd_entry to local variables (actually in session) */ tmp_size = pwd_entry->g.size; if (_gnutls_mpi_scan_nz (&G, pwd_entry->g.data, &tmp_size) < 0) { gnutls_assert (); return GNUTLS_E_MPI_SCAN_FAILED; } tmp_size = pwd_entry->n.size; if (_gnutls_mpi_scan_nz (&N, pwd_entry->n.data, &tmp_size) < 0) { gnutls_assert (); return GNUTLS_E_MPI_SCAN_FAILED; } tmp_size = pwd_entry->v.size; if (_gnutls_mpi_scan_nz (&V, pwd_entry->v.data, &tmp_size) < 0) { gnutls_assert (); return GNUTLS_E_MPI_SCAN_FAILED; } /* Calculate: B = (k*v + g^b) % N */ B = _gnutls_calc_srp_B (&_b, G, N, V); if (B == NULL) { gnutls_assert (); return GNUTLS_E_MEMORY_ERROR; } if (_gnutls_mpi_print (NULL, &n_b, B) != 0) { gnutls_assert (); return GNUTLS_E_MPI_PRINT_FAILED; } /* Allocate size to hold the N, g, s, B */ data_size = (pwd_entry->n.size + 2 + pwd_entry->g.size + 2 + pwd_entry->salt.size + 1) + (n_b + 2); (*data) = gnutls_malloc (data_size); if ((*data) == NULL) { gnutls_assert (); return GNUTLS_E_MEMORY_ERROR; } /* copy N (mod n) */ data_n = *data; _gnutls_write_datum16 (data_n, pwd_entry->n); /* copy G (generator) to data */ data_g = &data_n[2 + pwd_entry->n.size]; _gnutls_write_datum16 (data_g, pwd_entry->g); /* copy the salt */ data_s = &data_g[2 + pwd_entry->g.size]; _gnutls_write_datum8 (data_s, pwd_entry->salt); /* Copy the B value */ data_b = &data_s[1 + pwd_entry->salt.size]; if (_gnutls_mpi_print (&data_b[2], &n_b, B) != 0) { gnutls_assert(); return GNUTLS_E_MPI_PRINT_FAILED; } _gnutls_write_uint16 (n_b, data_b); _gnutls_hard_log ("INT: SRP B[%d]: %s\n", n_b, _gnutls_bin2hex (&data_b[2], n_b, buf, sizeof (buf))); _gnutls_srp_entry_free (pwd_entry); return data_size; }
/* Parses an X509 DN in the asn1_struct, and returns the requested * DN OID. * * asn1_rdn_name must be a string in the form "tbsCertificate.issuer.rdnSequence". * That is to point in the rndSequence. * * indx specifies which OID to return. Ie 0 means return the first specified * OID found, 1 the second etc. */ int _gnutls_x509_get_dn_oid(ASN1_TYPE asn1_struct, const char *asn1_rdn_name, int indx, void *_oid, size_t * sizeof_oid) { int k2, k1, result; char tmpbuffer1[ASN1_MAX_NAME_SIZE]; char tmpbuffer2[ASN1_MAX_NAME_SIZE]; char tmpbuffer3[ASN1_MAX_NAME_SIZE]; char value[256]; char oid[MAX_OID_SIZE]; int len; int i = 0; k1 = 0; do { k1++; /* create a string like "tbsCertList.issuer.rdnSequence.?1" */ if (asn1_rdn_name[0] != 0) snprintf(tmpbuffer1, sizeof(tmpbuffer1), "%s.?%u", asn1_rdn_name, k1); else snprintf(tmpbuffer1, sizeof(tmpbuffer1), "?%u", k1); len = sizeof(value) - 1; result = asn1_read_value(asn1_struct, tmpbuffer1, value, &len); if (result == ASN1_ELEMENT_NOT_FOUND) { gnutls_assert(); break; } if (result != ASN1_VALUE_NOT_FOUND) { gnutls_assert(); result = _gnutls_asn2err(result); goto cleanup; } k2 = 0; do { /* Move to the attibute type and values */ k2++; if (tmpbuffer1[0] != 0) snprintf(tmpbuffer2, sizeof(tmpbuffer2), "%s.?%u", tmpbuffer1, k2); else snprintf(tmpbuffer2, sizeof(tmpbuffer2), "?%u", k2); /* Try to read the RelativeDistinguishedName attributes. */ len = sizeof(value) - 1; result = asn1_read_value(asn1_struct, tmpbuffer2, value, &len); if (result == ASN1_ELEMENT_NOT_FOUND) { break; } if (result != ASN1_VALUE_NOT_FOUND) { gnutls_assert(); result = _gnutls_asn2err(result); goto cleanup; } /* Read the OID */ _gnutls_str_cpy(tmpbuffer3, sizeof(tmpbuffer3), tmpbuffer2); _gnutls_str_cat(tmpbuffer3, sizeof(tmpbuffer3), ".type"); len = sizeof(oid) - 1; result = asn1_read_value(asn1_struct, tmpbuffer3, oid, &len); if (result == ASN1_ELEMENT_NOT_FOUND) break; else if (result != ASN1_SUCCESS) { gnutls_assert(); result = _gnutls_asn2err(result); goto cleanup; } if (indx == i++) { /* Found the OID */ len = strlen(oid) + 1; if (*sizeof_oid < (unsigned) len) { *sizeof_oid = len; gnutls_assert(); return GNUTLS_E_SHORT_MEMORY_BUFFER; } memcpy(_oid, oid, len); *sizeof_oid = len - 1; return 0; } } while (1); } while (1); gnutls_assert(); result = GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; cleanup: return result; }
int _gnutls_x509_get_dn(ASN1_TYPE asn1_struct, const char *asn1_rdn_name, gnutls_datum_t * dn) { gnutls_buffer_st out_str; int k2, k1, result; char tmpbuffer1[ASN1_MAX_NAME_SIZE]; char tmpbuffer2[ASN1_MAX_NAME_SIZE]; char tmpbuffer3[ASN1_MAX_NAME_SIZE]; uint8_t value[MAX_STRING_LEN]; gnutls_datum_t td = { NULL, 0 }, tvd = { NULL, 0}; const char *ldap_desc; char oid[MAX_OID_SIZE]; int len; _gnutls_buffer_init(&out_str); k1 = 0; do { k1++; /* create a string like "tbsCertList.issuer.rdnSequence.?1" */ if (asn1_rdn_name[0] != 0) snprintf(tmpbuffer1, sizeof(tmpbuffer1), "%s.?%u", asn1_rdn_name, k1); else snprintf(tmpbuffer1, sizeof(tmpbuffer1), "?%u", k1); len = sizeof(value) - 1; result = asn1_read_value(asn1_struct, tmpbuffer1, value, &len); if (result == ASN1_ELEMENT_NOT_FOUND) { if (k1 == 1) { gnutls_assert(); result = GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; goto cleanup; } break; } if (result != ASN1_VALUE_NOT_FOUND) { gnutls_assert(); result = _gnutls_asn2err(result); goto cleanup; } k2 = 0; do { /* Move to the attibute type and values */ k2++; if (tmpbuffer1[0] != 0) snprintf(tmpbuffer2, sizeof(tmpbuffer2), "%s.?%u", tmpbuffer1, k2); else snprintf(tmpbuffer2, sizeof(tmpbuffer2), "?%u", k2); /* Try to read the RelativeDistinguishedName attributes. */ len = sizeof(value) - 1; result = asn1_read_value(asn1_struct, tmpbuffer2, value, &len); if (result == ASN1_ELEMENT_NOT_FOUND) break; if (result != ASN1_VALUE_NOT_FOUND) { gnutls_assert(); result = _gnutls_asn2err(result); goto cleanup; } /* Read the OID */ _gnutls_str_cpy(tmpbuffer3, sizeof(tmpbuffer3), tmpbuffer2); _gnutls_str_cat(tmpbuffer3, sizeof(tmpbuffer3), ".type"); len = sizeof(oid) - 1; result = asn1_read_value(asn1_struct, tmpbuffer3, oid, &len); if (result == ASN1_ELEMENT_NOT_FOUND) break; else if (result != ASN1_SUCCESS) { gnutls_assert(); result = _gnutls_asn2err(result); goto cleanup; } /* Read the Value */ _gnutls_str_cpy(tmpbuffer3, sizeof(tmpbuffer3), tmpbuffer2); _gnutls_str_cat(tmpbuffer3, sizeof(tmpbuffer3), ".value"); len = 0; result = _gnutls_x509_read_value(asn1_struct, tmpbuffer3, &tvd); if (result < 0) { gnutls_assert(); goto cleanup; } #define STR_APPEND(y) if ((result=_gnutls_buffer_append_str( &out_str, y)) < 0) { \ gnutls_assert(); \ goto cleanup; \ } #define DATA_APPEND(x,y) if ((result=_gnutls_buffer_append_data( &out_str, x,y)) < 0) { \ gnutls_assert(); \ goto cleanup; \ } /* The encodings of adjoining RelativeDistinguishedNames are separated * by a comma character (',' ASCII 44). */ /* Where there is a multi-valued RDN, the outputs from adjoining * AttributeTypeAndValues are separated by a plus ('+' ASCII 43) * character. */ if (k1 != 1) { /* the first time do not append a comma */ if (k2 != 1) { /* adjoining multi-value RDN */ STR_APPEND("+"); } else { STR_APPEND(","); } } ldap_desc = gnutls_x509_dn_oid_name(oid, GNUTLS_X509_DN_OID_RETURN_OID); STR_APPEND(ldap_desc); STR_APPEND("="); result = _gnutls_x509_dn_to_string(oid, tvd.data, tvd.size, &td); if (result < 0) { gnutls_assert(); _gnutls_debug_log ("Cannot parse OID: '%s' with value '%s'\n", oid, _gnutls_bin2hex(tvd.data, tvd.size, tmpbuffer3, sizeof (tmpbuffer3), NULL)); goto cleanup; } DATA_APPEND(td.data, td.size); _gnutls_free_datum(&td); _gnutls_free_datum(&tvd); } while (1); } while (1); result = _gnutls_buffer_to_datum(&out_str, dn, 1); if (result < 0) gnutls_assert(); goto cleanup1; cleanup: _gnutls_buffer_clear(&out_str); cleanup1: _gnutls_free_datum(&td); _gnutls_free_datum(&tvd); return result; }
/* * This function writes and encodes the parameters for DSS or RSA keys. * This is the "signatureAlgorithm" fields. */ int _gnutls_x509_write_sig_params (ASN1_TYPE dst, const char *dst_name, gnutls_pk_algorithm_t pk_algorithm, gnutls_digest_algorithm_t dig, bigint_t * params, int params_size) { gnutls_datum_t der; int result; char name[128]; const char *pk; _gnutls_str_cpy (name, sizeof (name), dst_name); _gnutls_str_cat (name, sizeof (name), ".algorithm"); pk = _gnutls_x509_sign_to_oid (pk_algorithm, HASH2MAC (dig)); if (pk == NULL) { gnutls_assert (); return GNUTLS_E_INVALID_REQUEST; } /* write the OID. */ result = asn1_write_value (dst, name, pk, 1); if (result != ASN1_SUCCESS) { gnutls_assert (); return _gnutls_asn2err (result); } _gnutls_str_cpy (name, sizeof (name), dst_name); _gnutls_str_cat (name, sizeof (name), ".parameters"); if (pk_algorithm == GNUTLS_PK_DSA) { result = _gnutls_x509_write_dsa_params (params, params_size, &der); if (result < 0) { gnutls_assert (); return result; } result = asn1_write_value (dst, name, der.data, der.size); _gnutls_free_datum (&der); if (result != ASN1_SUCCESS) { gnutls_assert (); return _gnutls_asn2err (result); } } else { /* RSA */ result = asn1_write_value (dst, name, NULL, 0); if (result != ASN1_SUCCESS && result != ASN1_ELEMENT_NOT_FOUND) { /* Here we ignore the element not found error, since this * may have been disabled before. */ gnutls_assert (); return _gnutls_asn2err (result); } } return 0; }
/* This function will convert an attribute value, specified by the OID, * to a string. The result will be a null terminated string. * * res may be null. This will just return the res_size, needed to * hold the string. */ int _gnutls_x509_oid_data2string (const char *oid, void *value, int value_size, char *res, size_t * res_size) { char str[MAX_STRING_LEN], tmpname[128]; const char *ANAME = NULL; int CHOICE = -1, len = -1, result; ASN1_TYPE tmpasn = ASN1_TYPE_EMPTY; char asn1_err[ASN1_MAX_ERROR_DESCRIPTION_SIZE] = ""; if (value == NULL || value_size <= 0 || res_size == NULL) { gnutls_assert (); return GNUTLS_E_INVALID_REQUEST; } if (_gnutls_x509_oid_data_printable (oid) == 0) { gnutls_assert (); return GNUTLS_E_INTERNAL_ERROR; } ANAME = _gnutls_x509_oid2asn_string (oid); CHOICE = _gnutls_x509_oid_data_choice (oid); if (ANAME == NULL) { gnutls_assert (); return GNUTLS_E_INTERNAL_ERROR; } if ((result = asn1_create_element (_gnutls_get_pkix (), ANAME, &tmpasn)) != ASN1_SUCCESS) { gnutls_assert (); return _gnutls_asn2err (result); } if ((result = asn1_der_decoding (&tmpasn, value, value_size, asn1_err)) != ASN1_SUCCESS) { gnutls_assert (); _gnutls_debug_log ("asn1_der_decoding: %s:%s\n", str, asn1_err); asn1_delete_structure (&tmpasn); return _gnutls_asn2err (result); } /* If this is a choice then we read the choice. Otherwise it * is the value; */ len = sizeof (str) - 1; if ((result = asn1_read_value (tmpasn, "", str, &len)) != ASN1_SUCCESS) { /* CHOICE */ gnutls_assert (); asn1_delete_structure (&tmpasn); return _gnutls_asn2err (result); } if (CHOICE == 0) { str[len] = 0; /* Refuse to deal with strings containing NULs. */ if (strlen (str) != len) return GNUTLS_E_ASN1_DER_ERROR; if (res) _gnutls_str_cpy (res, *res_size, str); *res_size = len; asn1_delete_structure (&tmpasn); } else { /* CHOICE */ int non_printable = 0, teletex = 0; str[len] = 0; /* Note that we do not support strings other than * UTF-8 (thus ASCII as well). */ if (strcmp (str, "printableString") != 0 && strcmp (str, "ia5String") != 0 && strcmp (str, "utf8String") != 0) { non_printable = 1; } if (strcmp (str, "teletexString") == 0) teletex = 1; _gnutls_str_cpy (tmpname, sizeof (tmpname), str); len = sizeof (str) - 1; if ((result = asn1_read_value (tmpasn, tmpname, str, &len)) != ASN1_SUCCESS) { asn1_delete_structure (&tmpasn); return _gnutls_asn2err (result); } asn1_delete_structure (&tmpasn); if (teletex != 0) { int ascii = 0, i; /* HACK: if the teletex string contains only ascii * characters then treat it as printable. */ for (i = 0; i < len; i++) if (!isascii (str[i])) ascii = 1; if (ascii == 0) non_printable = 0; } if (non_printable == 0) { str[len] = 0; /* Refuse to deal with strings containing NULs. */ if (strlen (str) != len) return GNUTLS_E_ASN1_DER_ERROR; if (res) _gnutls_str_cpy (res, *res_size, str); *res_size = len; } else { result = _gnutls_x509_data2hex (str, len, res, res_size); if (result < 0) { gnutls_assert (); return result; } } } return 0; }
/* Sets an X509 DN in the asn1_struct, and puts the given OID in the DN. * The input is assumed to be raw data. * * asn1_rdn_name must be a string in the form "tbsCertificate.issuer". * That is to point before the rndSequence. * */ int _gnutls_x509_set_dn_oid(ASN1_TYPE asn1_struct, const char *asn1_name, const char *given_oid, int raw_flag, const char *name, int sizeof_name) { int result; char tmp[ASN1_MAX_NAME_SIZE], asn1_rdn_name[ASN1_MAX_NAME_SIZE]; if (sizeof_name == 0 || name == NULL) { gnutls_assert(); return GNUTLS_E_INVALID_REQUEST; } /* create the rdnSequence */ result = asn1_write_value(asn1_struct, asn1_name, "rdnSequence", 1); if (result != ASN1_SUCCESS) { gnutls_assert(); return _gnutls_asn2err(result); } _gnutls_str_cpy(asn1_rdn_name, sizeof(asn1_rdn_name), asn1_name); _gnutls_str_cat(asn1_rdn_name, sizeof(asn1_rdn_name), ".rdnSequence"); /* create a new element */ result = asn1_write_value(asn1_struct, asn1_rdn_name, "NEW", 1); if (result != ASN1_SUCCESS) { gnutls_assert(); return _gnutls_asn2err(result); } _gnutls_str_cpy(tmp, sizeof(tmp), asn1_rdn_name); _gnutls_str_cat(tmp, sizeof(tmp), ".?LAST"); /* create the set with only one element */ result = asn1_write_value(asn1_struct, tmp, "NEW", 1); if (result != ASN1_SUCCESS) { gnutls_assert(); return _gnutls_asn2err(result); } /* Encode and write the data */ _gnutls_str_cpy(tmp, sizeof(tmp), asn1_rdn_name); _gnutls_str_cat(tmp, sizeof(tmp), ".?LAST.?LAST"); if (!raw_flag) { result = _gnutls_x509_encode_and_write_attribute(given_oid, asn1_struct, tmp, name, sizeof_name, 0); } else { result = _gnutls_x509_write_attribute(given_oid, asn1_struct, tmp, name, sizeof_name); } if (result < 0) { gnutls_assert(); return result; } return 0; }
/* Send the first key exchange message ( g, n, s) and append the verifier algorithm number * Data is allocated by the caller, and should have data_size size. */ int _gnutls_gen_srp_server_kx(gnutls_session_t session, gnutls_buffer_st * data) { int ret; char *username; SRP_PWD_ENTRY *pwd_entry; srp_server_auth_info_t info; size_t tmp_size; extension_priv_data_t epriv; srp_ext_st *priv; ret = _gnutls_ext_get_session_data(session, GNUTLS_EXTENSION_SRP, &epriv); if (ret < 0) { /* peer didn't send a username */ gnutls_assert(); return GNUTLS_E_UNKNOWN_SRP_USERNAME; } priv = epriv; if ((ret = _gnutls_auth_info_set(session, GNUTLS_CRD_SRP, sizeof(srp_server_auth_info_st), 1)) < 0) { gnutls_assert(); return ret; } info = _gnutls_get_auth_info(session, GNUTLS_CRD_SRP); if (info == NULL) return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR); username = info->username; _gnutls_str_cpy(username, MAX_USERNAME_SIZE, priv->username); ret = _gnutls_srp_pwd_read_entry(session, username, &pwd_entry); if (ret < 0) { gnutls_assert(); return ret; } /* copy from pwd_entry to local variables (actually in session) */ tmp_size = pwd_entry->g.size; if (_gnutls_mpi_init_scan_nz(&G, pwd_entry->g.data, tmp_size) < 0) { gnutls_assert(); ret = GNUTLS_E_MPI_SCAN_FAILED; goto cleanup; } tmp_size = pwd_entry->n.size; if (_gnutls_mpi_init_scan_nz(&N, pwd_entry->n.data, tmp_size) < 0) { gnutls_assert(); ret = GNUTLS_E_MPI_SCAN_FAILED; goto cleanup; } tmp_size = pwd_entry->v.size; if (_gnutls_mpi_init_scan_nz(&V, pwd_entry->v.data, tmp_size) < 0) { gnutls_assert(); ret = GNUTLS_E_MPI_SCAN_FAILED; goto cleanup; } /* Calculate: B = (k*v + g^b) % N */ B = _gnutls_calc_srp_B(&_b, G, N, V); if (B == NULL) { gnutls_assert(); ret = GNUTLS_E_MEMORY_ERROR; goto cleanup; } /* copy N (mod n) */ ret = _gnutls_buffer_append_data_prefix(data, 16, pwd_entry->n.data, pwd_entry->n.size); if (ret < 0) { gnutls_assert(); goto cleanup; } /* copy G (generator) to data */ ret = _gnutls_buffer_append_data_prefix(data, 16, pwd_entry->g.data, pwd_entry->g.size); if (ret < 0) { gnutls_assert(); goto cleanup; } /* copy the salt */ ret = _gnutls_buffer_append_data_prefix(data, 8, pwd_entry->salt.data, pwd_entry->salt.size); if (ret < 0) { gnutls_assert(); goto cleanup; } /* Copy the B value */ ret = _gnutls_buffer_append_mpi(data, 16, B, 0); if (ret < 0) { gnutls_assert(); goto cleanup; } _gnutls_mpi_log("SRP B: ", B); ret = data->length; cleanup: _gnutls_srp_entry_free(pwd_entry); return ret; }
int set_extension (ASN1_TYPE asn, const char *root, const char *ext_id, const gnutls_datum_t * ext_data, unsigned int critical) { int result; int k, len; char name[ASN1_MAX_NAME_SIZE], name2[ASN1_MAX_NAME_SIZE]; char extnID[128]; /* Find the index of the given extension. */ k = 0; do { k++; if (root[0] != 0) snprintf (name, sizeof (name), "%s.?%u", root, k); else snprintf (name, sizeof (name), "?%u", k); len = sizeof (extnID) - 1; result = asn1_read_value (asn, name, extnID, &len); /* move to next */ if (result == ASN1_ELEMENT_NOT_FOUND) { break; } do { _gnutls_str_cpy (name2, sizeof (name2), name); _gnutls_str_cat (name2, sizeof (name2), ".extnID"); len = sizeof (extnID) - 1; result = asn1_read_value (asn, name2, extnID, &len); if (result == ASN1_ELEMENT_NOT_FOUND) { gnutls_assert (); break; } else if (result != ASN1_SUCCESS) { gnutls_assert (); return _gnutls_asn2err (result); } /* Handle Extension */ if (strcmp (extnID, ext_id) == 0) { /* extension was found */ return overwrite_extension (asn, root, k, ext_data, critical); } } while (0); } while (1); if (result == ASN1_ELEMENT_NOT_FOUND) { return add_extension (asn, root, ext_id, ext_data, critical); } else { gnutls_assert (); return _gnutls_asn2err (result); } return 0; }
static int write_complex_string(ASN1_TYPE asn_struct, const char *where, const struct oid_to_string *oentry, const uint8_t * data, size_t data_size) { char tmp[128]; ASN1_TYPE c2; int result; const char *string_type; unsigned int i; result = asn1_create_element(_gnutls_get_pkix(), oentry->asn_desc, &c2); if (result != ASN1_SUCCESS) { gnutls_assert(); return _gnutls_asn2err(result); } tmp[0] = 0; string_type = "printableString"; /* Check if the data is ASN.1 printable, and use * the UTF8 string type if not. */ for (i = 0; i < data_size; i++) { if (!is_printable(data[i])) { string_type = "utf8String"; break; } } /* if the type is a CHOICE then write the * type we'll use. */ result = asn1_write_value(c2, "", string_type, 1); if (result != ASN1_SUCCESS) { gnutls_assert(); result = _gnutls_asn2err(result); goto error; } _gnutls_str_cpy(tmp, sizeof(tmp), string_type); result = asn1_write_value(c2, tmp, data, data_size); if (result != ASN1_SUCCESS) { gnutls_assert(); result = _gnutls_asn2err(result); goto error; } result = _gnutls_x509_der_encode_and_copy(c2, "", asn_struct, where, 0); if (result < 0) { gnutls_assert(); goto error; } result = 0; error: asn1_delete_structure(&c2); return result; }
/* This will encode and write the AttributeTypeAndValue field. * 'multi' must be (0) if writing an AttributeTypeAndValue, and 1 if Attribute. * In all cases only one value is written. */ int _gnutls_x509_encode_and_write_attribute(const char *given_oid, ASN1_TYPE asn1_struct, const char *where, const void *_data, int data_size, int multi) { const uint8_t *data = _data; char tmp[128]; int result; const struct oid_to_string *oentry; oentry = get_oid_entry(given_oid); if (oentry == NULL) { gnutls_assert(); _gnutls_debug_log("Cannot find OID: %s\n", given_oid); return GNUTLS_E_X509_UNSUPPORTED_OID; } /* write the data (value) */ _gnutls_str_cpy(tmp, sizeof(tmp), where); _gnutls_str_cat(tmp, sizeof(tmp), ".value"); if (multi != 0) { /* if not writing an AttributeTypeAndValue, but an Attribute */ _gnutls_str_cat(tmp, sizeof(tmp), "s"); /* values */ result = asn1_write_value(asn1_struct, tmp, "NEW", 1); if (result != ASN1_SUCCESS) { gnutls_assert(); result = _gnutls_asn2err(result); goto error; } _gnutls_str_cat(tmp, sizeof(tmp), ".?LAST"); } if (oentry->asn_desc != NULL) { /* write a complex string API */ result = write_complex_string(asn1_struct, tmp, oentry, data, data_size); if (result < 0) return gnutls_assert_val(result); } else { /* write a simple string */ gnutls_datum_t td; td.data = (void *) data; td.size = data_size; result = _gnutls_x509_write_string(asn1_struct, tmp, &td, oentry->etype); if (result < 0) { gnutls_assert(); goto error; } } /* write the type */ _gnutls_str_cpy(tmp, sizeof(tmp), where); _gnutls_str_cat(tmp, sizeof(tmp), ".type"); result = asn1_write_value(asn1_struct, tmp, given_oid, 1); if (result != ASN1_SUCCESS) { gnutls_assert(); result = _gnutls_asn2err(result); goto error; } result = 0; error: return result; }
/*- * _gnutls_x509_pkix_sign - This function will sign a CRL or a certificate with a key * @src: should contain an ASN1_TYPE * @issuer: is the certificate of the certificate issuer * @issuer_key: holds the issuer's private key * * This function will sign a CRL or a certificate with the issuer's private key, and * will copy the issuer's information into the CRL or certificate. * * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a * negative error value. -*/ int _gnutls_x509_pkix_sign (ASN1_TYPE src, const char *src_name, gnutls_digest_algorithm_t dig, gnutls_x509_crt_t issuer, gnutls_x509_privkey_t issuer_key) { int result; gnutls_datum_t signature; char name[128]; /* Step 1. Copy the issuer's name into the certificate. */ _gnutls_str_cpy (name, sizeof (name), src_name); _gnutls_str_cat (name, sizeof (name), ".issuer"); result = asn1_copy_node (src, name, issuer->cert, "tbsCertificate.subject"); if (result != ASN1_SUCCESS) { gnutls_assert (); return _gnutls_asn2err (result); } /* Step 1.5. Write the signature stuff in the tbsCertificate. */ _gnutls_str_cpy (name, sizeof (name), src_name); _gnutls_str_cat (name, sizeof (name), ".signature"); result = _gnutls_x509_write_sig_params (src, name, issuer_key->pk_algorithm, dig, issuer_key->params, issuer_key->params_size); if (result < 0) { gnutls_assert (); return result; } /* Step 2. Sign the certificate. */ result = _gnutls_x509_sign_tbs (src, src_name, dig, issuer_key, &signature); if (result < 0) { gnutls_assert (); return result; } /* write the signature (bits) */ result = asn1_write_value (src, "signature", signature.data, signature.size * 8); _gnutls_free_datum (&signature); if (result != ASN1_SUCCESS) { gnutls_assert (); return _gnutls_asn2err (result); } /* Step 3. Move up and write the AlgorithmIdentifier, which is also * the same. */ result = _gnutls_x509_write_sig_params (src, "signatureAlgorithm", issuer_key->pk_algorithm, dig, issuer_key->params, issuer_key->params_size); if (result < 0) { gnutls_assert (); return result; } return 0; }
static int decode_complex_string(const struct oid_to_string *oentry, void *value, int value_size, gnutls_datum_t * out) { char str[MAX_STRING_LEN], tmpname[128]; int len = -1, result; ASN1_TYPE tmpasn = ASN1_TYPE_EMPTY; char asn1_err[ASN1_MAX_ERROR_DESCRIPTION_SIZE] = ""; unsigned int etype; gnutls_datum_t td = {NULL, 0}; if (oentry->asn_desc == NULL) { gnutls_assert(); return GNUTLS_E_INTERNAL_ERROR; } if ((result = asn1_create_element(_gnutls_get_pkix(), oentry->asn_desc, &tmpasn)) != ASN1_SUCCESS) { gnutls_assert(); return _gnutls_asn2err(result); } if ((result = asn1_der_decoding(&tmpasn, value, value_size, asn1_err)) != ASN1_SUCCESS) { gnutls_assert(); _gnutls_debug_log("asn1_der_decoding: %s\n", asn1_err); asn1_delete_structure(&tmpasn); return _gnutls_asn2err(result); } /* Read the type of choice. */ len = sizeof(str) - 1; if ((result = asn1_read_value(tmpasn, "", str, &len)) != ASN1_SUCCESS) { /* CHOICE */ gnutls_assert(); asn1_delete_structure(&tmpasn); return _gnutls_asn2err(result); } str[len] = 0; /* We set the etype on the strings that may need * some conversion to UTF-8. The INVALID flag indicates * no conversion needed */ if (strcmp(str, "teletexString") == 0) etype = ASN1_ETYPE_TELETEX_STRING; else if (strcmp(str, "bmpString") == 0) etype = ASN1_ETYPE_BMP_STRING; else if (strcmp(str, "universalString") == 0) etype = ASN1_ETYPE_UNIVERSAL_STRING; else etype = ASN1_ETYPE_INVALID; _gnutls_str_cpy(tmpname, sizeof(tmpname), str); result = _gnutls_x509_read_value(tmpasn, tmpname, &td); asn1_delete_structure(&tmpasn); if (result < 0) return gnutls_assert_val(result); if (etype != ASN1_ETYPE_INVALID) { result = make_printable_string(etype, &td, out); _gnutls_free_datum(&td); if (result < 0) return gnutls_assert_val(result); } else { out->data = td.data; out->size = td.size; /* _gnutls_x509_read_value always null terminates */ } /* Refuse to deal with strings containing NULs. */ if (strlen((void *) out->data) != (size_t) out->size) { _gnutls_free_datum(out); return gnutls_assert_val(GNUTLS_E_ASN1_DER_ERROR); } return 0; }
static int write_attributes (gnutls_pkcs12_bag_t bag, int elem, ASN1_TYPE c2, const char *where) { int result; char root[128]; /* If the bag attributes are empty, then write * nothing to the attribute field. */ if (bag->element[elem].friendly_name == NULL && bag->element[elem].local_key_id.data == NULL) { /* no attributes */ result = asn1_write_value (c2, where, NULL, 0); if (result != ASN1_SUCCESS) { gnutls_assert (); return _gnutls_asn2err (result); } return 0; } if (bag->element[elem].local_key_id.data != NULL) { /* Add a new Attribute */ result = asn1_write_value (c2, where, "NEW", 1); if (result != ASN1_SUCCESS) { gnutls_assert (); return _gnutls_asn2err (result); } _gnutls_str_cpy (root, sizeof (root), where); _gnutls_str_cat (root, sizeof (root), ".?LAST"); result = _gnutls_x509_encode_and_write_attribute (KEY_ID_OID, c2, root, bag-> element[elem].local_key_id. data, bag-> element[elem].local_key_id. size, 1); if (result < 0) { gnutls_assert (); return result; } } if (bag->element[elem].friendly_name != NULL) { opaque *name; int size, i; const char *p; /* Add a new Attribute */ result = asn1_write_value (c2, where, "NEW", 1); if (result != ASN1_SUCCESS) { gnutls_assert (); return _gnutls_asn2err (result); } /* convert name to BMPString */ size = strlen (bag->element[elem].friendly_name) * 2; name = gnutls_malloc (size); if (name == NULL) { gnutls_assert (); return GNUTLS_E_MEMORY_ERROR; } p = bag->element[elem].friendly_name; for (i = 0; i < size; i += 2) { name[i] = 0; name[i + 1] = *p; p++; } _gnutls_str_cpy (root, sizeof (root), where); _gnutls_str_cat (root, sizeof (root), ".?LAST"); result = _gnutls_x509_encode_and_write_attribute (FRIENDLY_NAME_OID, c2, root, name, size, 1); gnutls_free (name); if (result < 0) { gnutls_assert (); return result; } } return 0; }
int get_extension (ASN1_TYPE asn, const char *root, const char *extension_id, int indx, gnutls_datum_t * ret, unsigned int *_critical) { int k, result, len; char name[ASN1_MAX_NAME_SIZE], name2[ASN1_MAX_NAME_SIZE]; char str[1024]; char str_critical[10]; int critical = 0; char extnID[128]; gnutls_datum_t value; int indx_counter = 0; ret->data = NULL; ret->size = 0; k = 0; do { k++; snprintf (name, sizeof (name), "%s.?%u", root, k); len = sizeof (str) - 1; result = asn1_read_value (asn, name, str, &len); /* move to next */ if (result == ASN1_ELEMENT_NOT_FOUND) { break; } do { _gnutls_str_cpy (name2, sizeof (name2), name); _gnutls_str_cat (name2, sizeof (name2), ".extnID"); len = sizeof (extnID) - 1; result = asn1_read_value (asn, name2, extnID, &len); if (result == ASN1_ELEMENT_NOT_FOUND) { gnutls_assert (); break; } else if (result != ASN1_SUCCESS) { gnutls_assert (); return _gnutls_asn2err (result); } /* Handle Extension */ if (strcmp (extnID, extension_id) == 0 && indx == indx_counter++) { /* extension was found */ /* read the critical status. */ _gnutls_str_cpy (name2, sizeof (name2), name); _gnutls_str_cat (name2, sizeof (name2), ".critical"); len = sizeof (str_critical); result = asn1_read_value (asn, name2, str_critical, &len); if (result == ASN1_ELEMENT_NOT_FOUND) { gnutls_assert (); break; } else if (result != ASN1_SUCCESS) { gnutls_assert (); return _gnutls_asn2err (result); } if (str_critical[0] == 'T') critical = 1; else critical = 0; /* read the value. */ _gnutls_str_cpy (name2, sizeof (name2), name); _gnutls_str_cat (name2, sizeof (name2), ".extnValue"); result = _gnutls_x509_read_value (asn, name2, &value); if (result < 0) { gnutls_assert (); return result; } ret->data = value.data; ret->size = value.size; if (_critical) *_critical = critical; return 0; } } while (0); } while (1); if (result == ASN1_ELEMENT_NOT_FOUND) { return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; } else { gnutls_assert (); return _gnutls_asn2err (result); } }