a_mbstr.c 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343
  1. /*
  2. * Copyright 1999-2017 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 <openssl/asn1.h>
  13. static int traverse_string(const unsigned char *p, int len, int inform,
  14. int (*rfunc) (unsigned long value, void *in),
  15. void *arg);
  16. static int in_utf8(unsigned long value, void *arg);
  17. static int out_utf8(unsigned long value, void *arg);
  18. static int type_str(unsigned long value, void *arg);
  19. static int cpy_asc(unsigned long value, void *arg);
  20. static int cpy_bmp(unsigned long value, void *arg);
  21. static int cpy_univ(unsigned long value, void *arg);
  22. static int cpy_utf8(unsigned long value, void *arg);
  23. /*
  24. * These functions take a string in UTF8, ASCII or multibyte form and a mask
  25. * of permissible ASN1 string types. It then works out the minimal type
  26. * (using the order Numeric < Printable < IA5 < T61 < BMP < Universal < UTF8)
  27. * and creates a string of the correct type with the supplied data. Yes this is
  28. * horrible: it has to be :-( The 'ncopy' form checks minimum and maximum
  29. * size limits too.
  30. */
  31. int ASN1_mbstring_copy(ASN1_STRING **out, const unsigned char *in, int len,
  32. int inform, unsigned long mask)
  33. {
  34. return ASN1_mbstring_ncopy(out, in, len, inform, mask, 0, 0);
  35. }
  36. int ASN1_mbstring_ncopy(ASN1_STRING **out, const unsigned char *in, int len,
  37. int inform, unsigned long mask,
  38. long minsize, long maxsize)
  39. {
  40. int str_type;
  41. int ret;
  42. char free_out;
  43. int outform, outlen = 0;
  44. ASN1_STRING *dest;
  45. unsigned char *p;
  46. int nchar;
  47. char strbuf[32];
  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. /* First do a string check and work out the number of characters */
  54. switch (inform) {
  55. case MBSTRING_BMP:
  56. if (len & 1) {
  57. ASN1err(ASN1_F_ASN1_MBSTRING_NCOPY,
  58. ASN1_R_INVALID_BMPSTRING_LENGTH);
  59. return -1;
  60. }
  61. nchar = len >> 1;
  62. break;
  63. case MBSTRING_UNIV:
  64. if (len & 3) {
  65. ASN1err(ASN1_F_ASN1_MBSTRING_NCOPY,
  66. 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. ASN1err(ASN1_F_ASN1_MBSTRING_NCOPY, ASN1_R_INVALID_UTF8STRING);
  77. return -1;
  78. }
  79. break;
  80. case MBSTRING_ASC:
  81. nchar = len;
  82. break;
  83. default:
  84. ASN1err(ASN1_F_ASN1_MBSTRING_NCOPY, ASN1_R_UNKNOWN_FORMAT);
  85. return -1;
  86. }
  87. if ((minsize > 0) && (nchar < minsize)) {
  88. ASN1err(ASN1_F_ASN1_MBSTRING_NCOPY, ASN1_R_STRING_TOO_SHORT);
  89. BIO_snprintf(strbuf, sizeof(strbuf), "%ld", minsize);
  90. ERR_add_error_data(2, "minsize=", strbuf);
  91. return -1;
  92. }
  93. if ((maxsize > 0) && (nchar > maxsize)) {
  94. ASN1err(ASN1_F_ASN1_MBSTRING_NCOPY, ASN1_R_STRING_TOO_LONG);
  95. BIO_snprintf(strbuf, sizeof(strbuf), "%ld", maxsize);
  96. ERR_add_error_data(2, "maxsize=", strbuf);
  97. return -1;
  98. }
  99. /* Now work out minimal type (if any) */
  100. if (traverse_string(in, len, inform, type_str, &mask) < 0) {
  101. ASN1err(ASN1_F_ASN1_MBSTRING_NCOPY, ASN1_R_ILLEGAL_CHARACTERS);
  102. return -1;
  103. }
  104. /* Now work out output format and string type */
  105. outform = MBSTRING_ASC;
  106. if (mask & B_ASN1_NUMERICSTRING)
  107. str_type = V_ASN1_NUMERICSTRING;
  108. else if (mask & B_ASN1_PRINTABLESTRING)
  109. str_type = V_ASN1_PRINTABLESTRING;
  110. else if (mask & B_ASN1_IA5STRING)
  111. str_type = V_ASN1_IA5STRING;
  112. else if (mask & B_ASN1_T61STRING)
  113. str_type = V_ASN1_T61STRING;
  114. else if (mask & B_ASN1_BMPSTRING) {
  115. str_type = V_ASN1_BMPSTRING;
  116. outform = MBSTRING_BMP;
  117. } else if (mask & B_ASN1_UNIVERSALSTRING) {
  118. str_type = V_ASN1_UNIVERSALSTRING;
  119. outform = MBSTRING_UNIV;
  120. } else {
  121. str_type = V_ASN1_UTF8STRING;
  122. outform = MBSTRING_UTF8;
  123. }
  124. if (!out)
  125. return str_type;
  126. if (*out) {
  127. free_out = 0;
  128. dest = *out;
  129. OPENSSL_free(dest->data);
  130. dest->data = NULL;
  131. dest->length = 0;
  132. dest->type = str_type;
  133. } else {
  134. free_out = 1;
  135. dest = ASN1_STRING_type_new(str_type);
  136. if (dest == NULL) {
  137. ASN1err(ASN1_F_ASN1_MBSTRING_NCOPY, ERR_R_MALLOC_FAILURE);
  138. return -1;
  139. }
  140. *out = dest;
  141. }
  142. /* If both the same type just copy across */
  143. if (inform == outform) {
  144. if (!ASN1_STRING_set(dest, in, len)) {
  145. ASN1err(ASN1_F_ASN1_MBSTRING_NCOPY, ERR_R_MALLOC_FAILURE);
  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. ASN1err(ASN1_F_ASN1_MBSTRING_NCOPY, ERR_R_MALLOC_FAILURE);
  174. return -1;
  175. }
  176. dest->length = outlen;
  177. dest->data = p;
  178. p[outlen] = 0;
  179. traverse_string(in, len, inform, cpyfunc, &p);
  180. return str_type;
  181. }
  182. /*
  183. * This function traverses a string and passes the value of each character to
  184. * an optional function along with a void * argument.
  185. */
  186. static int traverse_string(const unsigned char *p, int len, int inform,
  187. int (*rfunc) (unsigned long value, void *in),
  188. void *arg)
  189. {
  190. unsigned long value;
  191. int ret;
  192. while (len) {
  193. if (inform == MBSTRING_ASC) {
  194. value = *p++;
  195. len--;
  196. } else if (inform == MBSTRING_BMP) {
  197. value = *p++ << 8;
  198. value |= *p++;
  199. len -= 2;
  200. } else if (inform == MBSTRING_UNIV) {
  201. value = ((unsigned long)*p++) << 24;
  202. value |= ((unsigned long)*p++) << 16;
  203. value |= *p++ << 8;
  204. value |= *p++;
  205. len -= 4;
  206. } else {
  207. ret = UTF8_getc(p, len, &value);
  208. if (ret < 0)
  209. return -1;
  210. len -= ret;
  211. p += ret;
  212. }
  213. if (rfunc) {
  214. ret = rfunc(value, arg);
  215. if (ret <= 0)
  216. return ret;
  217. }
  218. }
  219. return 1;
  220. }
  221. /* Various utility functions for traverse_string */
  222. /* Just count number of characters */
  223. static int in_utf8(unsigned long value, void *arg)
  224. {
  225. int *nchar;
  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;
  234. outlen = arg;
  235. *outlen += UTF8_putc(NULL, -1, value);
  236. return 1;
  237. }
  238. /*
  239. * Determine the "type" of a string: check each character against a supplied
  240. * "mask".
  241. */
  242. static int type_str(unsigned long value, void *arg)
  243. {
  244. unsigned long types = *((unsigned long *)arg);
  245. const int native = value > INT_MAX ? INT_MAX : ossl_fromascii(value);
  246. if ((types & B_ASN1_NUMERICSTRING) && !(ossl_isdigit(native)
  247. || native == ' '))
  248. types &= ~B_ASN1_NUMERICSTRING;
  249. if ((types & B_ASN1_PRINTABLESTRING) && !ossl_isasn1print(native))
  250. types &= ~B_ASN1_PRINTABLESTRING;
  251. if ((types & B_ASN1_IA5STRING) && !ossl_isascii(native))
  252. types &= ~B_ASN1_IA5STRING;
  253. if ((types & B_ASN1_T61STRING) && (value > 0xff))
  254. types &= ~B_ASN1_T61STRING;
  255. if ((types & B_ASN1_BMPSTRING) && (value > 0xffff))
  256. types &= ~B_ASN1_BMPSTRING;
  257. if (!types)
  258. return -1;
  259. *((unsigned long *)arg) = types;
  260. return 1;
  261. }
  262. /* Copy one byte per character ASCII like strings */
  263. static int cpy_asc(unsigned long value, void *arg)
  264. {
  265. unsigned char **p, *q;
  266. p = arg;
  267. q = *p;
  268. *q = (unsigned char)value;
  269. (*p)++;
  270. return 1;
  271. }
  272. /* Copy two byte per character BMPStrings */
  273. static int cpy_bmp(unsigned long value, void *arg)
  274. {
  275. unsigned char **p, *q;
  276. p = arg;
  277. q = *p;
  278. *q++ = (unsigned char)((value >> 8) & 0xff);
  279. *q = (unsigned char)(value & 0xff);
  280. *p += 2;
  281. return 1;
  282. }
  283. /* Copy four byte per character UniversalStrings */
  284. static int cpy_univ(unsigned long value, void *arg)
  285. {
  286. unsigned char **p, *q;
  287. p = arg;
  288. q = *p;
  289. *q++ = (unsigned char)((value >> 24) & 0xff);
  290. *q++ = (unsigned char)((value >> 16) & 0xff);
  291. *q++ = (unsigned char)((value >> 8) & 0xff);
  292. *q = (unsigned char)(value & 0xff);
  293. *p += 4;
  294. return 1;
  295. }
  296. /* Copy to a UTF8String */
  297. static int cpy_utf8(unsigned long value, void *arg)
  298. {
  299. unsigned char **p;
  300. int ret;
  301. p = arg;
  302. /* We already know there is enough room so pass 0xff as the length */
  303. ret = UTF8_putc(*p, 0xff, value);
  304. *p += ret;
  305. return 1;
  306. }