a_mbstr.c 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353
  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. ASN1_STRING_set0(dest, NULL, 0);
  128. dest->type = str_type;
  129. } else {
  130. free_out = 1;
  131. dest = ASN1_STRING_type_new(str_type);
  132. if (dest == NULL) {
  133. ERR_raise(ERR_LIB_ASN1, ERR_R_ASN1_LIB);
  134. return -1;
  135. }
  136. *out = dest;
  137. }
  138. /* If both the same type just copy across */
  139. if (inform == outform) {
  140. if (!ASN1_STRING_set(dest, in, len)) {
  141. if (free_out) {
  142. ASN1_STRING_free(dest);
  143. *out = NULL;
  144. }
  145. ERR_raise(ERR_LIB_ASN1, ERR_R_ASN1_LIB);
  146. return -1;
  147. }
  148. return str_type;
  149. }
  150. /* Work out how much space the destination will need */
  151. switch (outform) {
  152. case MBSTRING_ASC:
  153. outlen = nchar;
  154. cpyfunc = cpy_asc;
  155. break;
  156. case MBSTRING_BMP:
  157. outlen = nchar << 1;
  158. cpyfunc = cpy_bmp;
  159. break;
  160. case MBSTRING_UNIV:
  161. outlen = nchar << 2;
  162. cpyfunc = cpy_univ;
  163. break;
  164. case MBSTRING_UTF8:
  165. outlen = 0;
  166. traverse_string(in, len, inform, out_utf8, &outlen);
  167. cpyfunc = cpy_utf8;
  168. break;
  169. }
  170. if ((p = OPENSSL_malloc(outlen + 1)) == NULL) {
  171. if (free_out) {
  172. ASN1_STRING_free(dest);
  173. *out = NULL;
  174. }
  175. return -1;
  176. }
  177. dest->length = outlen;
  178. dest->data = p;
  179. p[outlen] = 0;
  180. traverse_string(in, len, inform, cpyfunc, &p);
  181. return str_type;
  182. }
  183. /*
  184. * This function traverses a string and passes the value of each character to
  185. * an optional function along with a void * argument.
  186. */
  187. static int traverse_string(const unsigned char *p, int len, int inform,
  188. int (*rfunc) (unsigned long value, void *in),
  189. void *arg)
  190. {
  191. unsigned long value;
  192. int ret;
  193. while (len) {
  194. if (inform == MBSTRING_ASC) {
  195. value = *p++;
  196. len--;
  197. } else if (inform == MBSTRING_BMP) {
  198. value = *p++ << 8;
  199. value |= *p++;
  200. len -= 2;
  201. } else if (inform == MBSTRING_UNIV) {
  202. value = ((unsigned long)*p++) << 24;
  203. value |= ((unsigned long)*p++) << 16;
  204. value |= *p++ << 8;
  205. value |= *p++;
  206. len -= 4;
  207. } else {
  208. ret = UTF8_getc(p, len, &value);
  209. if (ret < 0)
  210. return -1;
  211. len -= ret;
  212. p += ret;
  213. }
  214. if (rfunc) {
  215. ret = rfunc(value, arg);
  216. if (ret <= 0)
  217. return ret;
  218. }
  219. }
  220. return 1;
  221. }
  222. /* Various utility functions for traverse_string */
  223. /* Just count number of characters */
  224. static int in_utf8(unsigned long value, void *arg)
  225. {
  226. int *nchar;
  227. if (!is_unicode_valid(value))
  228. return -2;
  229. nchar = arg;
  230. (*nchar)++;
  231. return 1;
  232. }
  233. /* Determine size of output as a UTF8 String */
  234. static int out_utf8(unsigned long value, void *arg)
  235. {
  236. int *outlen, len;
  237. len = UTF8_putc(NULL, -1, value);
  238. if (len <= 0)
  239. return len;
  240. outlen = arg;
  241. *outlen += len;
  242. return 1;
  243. }
  244. /*
  245. * Determine the "type" of a string: check each character against a supplied
  246. * "mask".
  247. */
  248. static int type_str(unsigned long value, void *arg)
  249. {
  250. unsigned long types = *((unsigned long *)arg);
  251. const int native = value > INT_MAX ? INT_MAX : ossl_fromascii(value);
  252. if ((types & B_ASN1_NUMERICSTRING) && !(ossl_isdigit(native)
  253. || native == ' '))
  254. types &= ~B_ASN1_NUMERICSTRING;
  255. if ((types & B_ASN1_PRINTABLESTRING) && !ossl_isasn1print(native))
  256. types &= ~B_ASN1_PRINTABLESTRING;
  257. if ((types & B_ASN1_IA5STRING) && !ossl_isascii(native))
  258. types &= ~B_ASN1_IA5STRING;
  259. if ((types & B_ASN1_T61STRING) && (value > 0xff))
  260. types &= ~B_ASN1_T61STRING;
  261. if ((types & B_ASN1_BMPSTRING) && (value > 0xffff))
  262. types &= ~B_ASN1_BMPSTRING;
  263. if ((types & B_ASN1_UTF8STRING) && !is_unicode_valid(value))
  264. types &= ~B_ASN1_UTF8STRING;
  265. if (!types)
  266. return -1;
  267. *((unsigned long *)arg) = types;
  268. return 1;
  269. }
  270. /* Copy one byte per character ASCII like strings */
  271. static int cpy_asc(unsigned long value, void *arg)
  272. {
  273. unsigned char **p, *q;
  274. p = arg;
  275. q = *p;
  276. *q = (unsigned char)value;
  277. (*p)++;
  278. return 1;
  279. }
  280. /* Copy two byte per character BMPStrings */
  281. static int cpy_bmp(unsigned long value, void *arg)
  282. {
  283. unsigned char **p, *q;
  284. p = arg;
  285. q = *p;
  286. *q++ = (unsigned char)((value >> 8) & 0xff);
  287. *q = (unsigned char)(value & 0xff);
  288. *p += 2;
  289. return 1;
  290. }
  291. /* Copy four byte per character UniversalStrings */
  292. static int cpy_univ(unsigned long value, void *arg)
  293. {
  294. unsigned char **p, *q;
  295. p = arg;
  296. q = *p;
  297. *q++ = (unsigned char)((value >> 24) & 0xff);
  298. *q++ = (unsigned char)((value >> 16) & 0xff);
  299. *q++ = (unsigned char)((value >> 8) & 0xff);
  300. *q = (unsigned char)(value & 0xff);
  301. *p += 4;
  302. return 1;
  303. }
  304. /* Copy to a UTF8String */
  305. static int cpy_utf8(unsigned long value, void *arg)
  306. {
  307. unsigned char **p;
  308. int ret;
  309. p = arg;
  310. /* We already know there is enough room so pass 0xff as the length */
  311. ret = UTF8_putc(*p, 0xff, value);
  312. *p += ret;
  313. return 1;
  314. }