a_mbstr.c 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350
  1. /*
  2. * Copyright 1999-2021 The OpenSSL Project Authors. All Rights Reserved.
  3. *
  4. * Licensed under the Apache License 2.0 (the "License"). You may not use
  5. * this file except in compliance with the License. You can obtain a copy
  6. * in the file LICENSE in the source distribution or at
  7. * https://www.openssl.org/source/license.html
  8. */
  9. #include <stdio.h>
  10. #include "crypto/ctype.h"
  11. #include "internal/cryptlib.h"
  12. #include "internal/unicode.h"
  13. #include <openssl/asn1.h>
  14. static int traverse_string(const unsigned char *p, int len, int inform,
  15. int (*rfunc) (unsigned long value, void *in),
  16. void *arg);
  17. static int in_utf8(unsigned long value, void *arg);
  18. static int out_utf8(unsigned long value, void *arg);
  19. static int type_str(unsigned long value, void *arg);
  20. static int cpy_asc(unsigned long value, void *arg);
  21. static int cpy_bmp(unsigned long value, void *arg);
  22. static int cpy_univ(unsigned long value, void *arg);
  23. static int cpy_utf8(unsigned long value, void *arg);
  24. /*
  25. * These functions take a string in UTF8, ASCII or multibyte form and a mask
  26. * of permissible ASN1 string types. It then works out the minimal type
  27. * (using the order Numeric < Printable < IA5 < T61 < BMP < Universal < UTF8)
  28. * and creates a string of the correct type with the supplied data. Yes this is
  29. * horrible: it has to be :-( The 'ncopy' form checks minimum and maximum
  30. * size limits too.
  31. */
  32. int ASN1_mbstring_copy(ASN1_STRING **out, const unsigned char *in, int len,
  33. int inform, unsigned long mask)
  34. {
  35. return ASN1_mbstring_ncopy(out, in, len, inform, mask, 0, 0);
  36. }
  37. int ASN1_mbstring_ncopy(ASN1_STRING **out, const unsigned char *in, int len,
  38. int inform, unsigned long mask,
  39. long minsize, long maxsize)
  40. {
  41. int str_type;
  42. int ret;
  43. char free_out;
  44. int outform, outlen = 0;
  45. ASN1_STRING *dest;
  46. unsigned char *p;
  47. int nchar;
  48. int (*cpyfunc) (unsigned long, void *) = NULL;
  49. if (len == -1)
  50. len = strlen((const char *)in);
  51. if (!mask)
  52. mask = DIRSTRING_TYPE;
  53. if (len < 0)
  54. return -1;
  55. /* First do a string check and work out the number of characters */
  56. switch (inform) {
  57. case MBSTRING_BMP:
  58. if (len & 1) {
  59. ERR_raise(ERR_LIB_ASN1, ASN1_R_INVALID_BMPSTRING_LENGTH);
  60. return -1;
  61. }
  62. nchar = len >> 1;
  63. break;
  64. case MBSTRING_UNIV:
  65. if (len & 3) {
  66. ERR_raise(ERR_LIB_ASN1, ASN1_R_INVALID_UNIVERSALSTRING_LENGTH);
  67. return -1;
  68. }
  69. nchar = len >> 2;
  70. break;
  71. case MBSTRING_UTF8:
  72. nchar = 0;
  73. /* This counts the characters and does utf8 syntax checking */
  74. ret = traverse_string(in, len, MBSTRING_UTF8, in_utf8, &nchar);
  75. if (ret < 0) {
  76. ERR_raise(ERR_LIB_ASN1, ASN1_R_INVALID_UTF8STRING);
  77. return -1;
  78. }
  79. break;
  80. case MBSTRING_ASC:
  81. nchar = len;
  82. break;
  83. default:
  84. ERR_raise(ERR_LIB_ASN1, ASN1_R_UNKNOWN_FORMAT);
  85. return -1;
  86. }
  87. if ((minsize > 0) && (nchar < minsize)) {
  88. ERR_raise_data(ERR_LIB_ASN1, ASN1_R_STRING_TOO_SHORT,
  89. "minsize=%ld", minsize);
  90. return -1;
  91. }
  92. if ((maxsize > 0) && (nchar > maxsize)) {
  93. ERR_raise_data(ERR_LIB_ASN1, ASN1_R_STRING_TOO_LONG,
  94. "maxsize=%ld", maxsize);
  95. return -1;
  96. }
  97. /* Now work out minimal type (if any) */
  98. if (traverse_string(in, len, inform, type_str, &mask) < 0) {
  99. ERR_raise(ERR_LIB_ASN1, ASN1_R_ILLEGAL_CHARACTERS);
  100. return -1;
  101. }
  102. /* Now work out output format and string type */
  103. outform = MBSTRING_ASC;
  104. if (mask & B_ASN1_NUMERICSTRING)
  105. str_type = V_ASN1_NUMERICSTRING;
  106. else if (mask & B_ASN1_PRINTABLESTRING)
  107. str_type = V_ASN1_PRINTABLESTRING;
  108. else if (mask & B_ASN1_IA5STRING)
  109. str_type = V_ASN1_IA5STRING;
  110. else if (mask & B_ASN1_T61STRING)
  111. str_type = V_ASN1_T61STRING;
  112. else if (mask & B_ASN1_BMPSTRING) {
  113. str_type = V_ASN1_BMPSTRING;
  114. outform = MBSTRING_BMP;
  115. } else if (mask & B_ASN1_UNIVERSALSTRING) {
  116. str_type = V_ASN1_UNIVERSALSTRING;
  117. outform = MBSTRING_UNIV;
  118. } else {
  119. str_type = V_ASN1_UTF8STRING;
  120. outform = MBSTRING_UTF8;
  121. }
  122. if (!out)
  123. return str_type;
  124. if (*out) {
  125. free_out = 0;
  126. dest = *out;
  127. OPENSSL_free(dest->data);
  128. dest->data = NULL;
  129. dest->length = 0;
  130. dest->type = str_type;
  131. } else {
  132. free_out = 1;
  133. dest = ASN1_STRING_type_new(str_type);
  134. if (dest == NULL) {
  135. ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
  136. return -1;
  137. }
  138. *out = dest;
  139. }
  140. /* If both the same type just copy across */
  141. if (inform == outform) {
  142. if (!ASN1_STRING_set(dest, in, len)) {
  143. ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
  144. return -1;
  145. }
  146. return str_type;
  147. }
  148. /* Work out how much space the destination will need */
  149. switch (outform) {
  150. case MBSTRING_ASC:
  151. outlen = nchar;
  152. cpyfunc = cpy_asc;
  153. break;
  154. case MBSTRING_BMP:
  155. outlen = nchar << 1;
  156. cpyfunc = cpy_bmp;
  157. break;
  158. case MBSTRING_UNIV:
  159. outlen = nchar << 2;
  160. cpyfunc = cpy_univ;
  161. break;
  162. case MBSTRING_UTF8:
  163. outlen = 0;
  164. traverse_string(in, len, inform, out_utf8, &outlen);
  165. cpyfunc = cpy_utf8;
  166. break;
  167. }
  168. if ((p = OPENSSL_malloc(outlen + 1)) == NULL) {
  169. if (free_out)
  170. ASN1_STRING_free(dest);
  171. ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
  172. return -1;
  173. }
  174. dest->length = outlen;
  175. dest->data = p;
  176. p[outlen] = 0;
  177. traverse_string(in, len, inform, cpyfunc, &p);
  178. return str_type;
  179. }
  180. /*
  181. * This function traverses a string and passes the value of each character to
  182. * an optional function along with a void * argument.
  183. */
  184. static int traverse_string(const unsigned char *p, int len, int inform,
  185. int (*rfunc) (unsigned long value, void *in),
  186. void *arg)
  187. {
  188. unsigned long value;
  189. int ret;
  190. while (len) {
  191. if (inform == MBSTRING_ASC) {
  192. value = *p++;
  193. len--;
  194. } else if (inform == MBSTRING_BMP) {
  195. value = *p++ << 8;
  196. value |= *p++;
  197. len -= 2;
  198. } else if (inform == MBSTRING_UNIV) {
  199. value = ((unsigned long)*p++) << 24;
  200. value |= ((unsigned long)*p++) << 16;
  201. value |= *p++ << 8;
  202. value |= *p++;
  203. len -= 4;
  204. } else {
  205. ret = UTF8_getc(p, len, &value);
  206. if (ret < 0)
  207. return -1;
  208. len -= ret;
  209. p += ret;
  210. }
  211. if (rfunc) {
  212. ret = rfunc(value, arg);
  213. if (ret <= 0)
  214. return ret;
  215. }
  216. }
  217. return 1;
  218. }
  219. /* Various utility functions for traverse_string */
  220. /* Just count number of characters */
  221. static int in_utf8(unsigned long value, void *arg)
  222. {
  223. int *nchar;
  224. if (!is_unicode_valid(value))
  225. return -2;
  226. nchar = arg;
  227. (*nchar)++;
  228. return 1;
  229. }
  230. /* Determine size of output as a UTF8 String */
  231. static int out_utf8(unsigned long value, void *arg)
  232. {
  233. int *outlen, len;
  234. len = UTF8_putc(NULL, -1, value);
  235. if (len <= 0)
  236. return len;
  237. outlen = arg;
  238. *outlen += len;
  239. return 1;
  240. }
  241. /*
  242. * Determine the "type" of a string: check each character against a supplied
  243. * "mask".
  244. */
  245. static int type_str(unsigned long value, void *arg)
  246. {
  247. unsigned long types = *((unsigned long *)arg);
  248. const int native = value > INT_MAX ? INT_MAX : ossl_fromascii(value);
  249. if ((types & B_ASN1_NUMERICSTRING) && !(ossl_isdigit(native)
  250. || native == ' '))
  251. types &= ~B_ASN1_NUMERICSTRING;
  252. if ((types & B_ASN1_PRINTABLESTRING) && !ossl_isasn1print(native))
  253. types &= ~B_ASN1_PRINTABLESTRING;
  254. if ((types & B_ASN1_IA5STRING) && !ossl_isascii(native))
  255. types &= ~B_ASN1_IA5STRING;
  256. if ((types & B_ASN1_T61STRING) && (value > 0xff))
  257. types &= ~B_ASN1_T61STRING;
  258. if ((types & B_ASN1_BMPSTRING) && (value > 0xffff))
  259. types &= ~B_ASN1_BMPSTRING;
  260. if ((types & B_ASN1_UTF8STRING) && !is_unicode_valid(value))
  261. types &= ~B_ASN1_UTF8STRING;
  262. if (!types)
  263. return -1;
  264. *((unsigned long *)arg) = types;
  265. return 1;
  266. }
  267. /* Copy one byte per character ASCII like strings */
  268. static int cpy_asc(unsigned long value, void *arg)
  269. {
  270. unsigned char **p, *q;
  271. p = arg;
  272. q = *p;
  273. *q = (unsigned char)value;
  274. (*p)++;
  275. return 1;
  276. }
  277. /* Copy two byte per character BMPStrings */
  278. static int cpy_bmp(unsigned long value, void *arg)
  279. {
  280. unsigned char **p, *q;
  281. p = arg;
  282. q = *p;
  283. *q++ = (unsigned char)((value >> 8) & 0xff);
  284. *q = (unsigned char)(value & 0xff);
  285. *p += 2;
  286. return 1;
  287. }
  288. /* Copy four byte per character UniversalStrings */
  289. static int cpy_univ(unsigned long value, void *arg)
  290. {
  291. unsigned char **p, *q;
  292. p = arg;
  293. q = *p;
  294. *q++ = (unsigned char)((value >> 24) & 0xff);
  295. *q++ = (unsigned char)((value >> 16) & 0xff);
  296. *q++ = (unsigned char)((value >> 8) & 0xff);
  297. *q = (unsigned char)(value & 0xff);
  298. *p += 4;
  299. return 1;
  300. }
  301. /* Copy to a UTF8String */
  302. static int cpy_utf8(unsigned long value, void *arg)
  303. {
  304. unsigned char **p;
  305. int ret;
  306. p = arg;
  307. /* We already know there is enough room so pass 0xff as the length */
  308. ret = UTF8_putc(*p, 0xff, value);
  309. *p += ret;
  310. return 1;
  311. }