diff --git a/ip/xfrm_state.c b/ip/xfrm_state.c index d6d21438..cc5e8880 100644 --- a/ip/xfrm_state.c +++ b/ip/xfrm_state.c @@ -114,34 +114,35 @@ static int xfrm_algo_parse(struct xfrm_algo *alg, enum xfrm_attr_type_t type, strncpy(alg->alg_name, name, sizeof(alg->alg_name)); if (slen > 2 && strncmp(key, "0x", 2) == 0) { - /* - * XXX: fix me!! + /* split two chars "0x" from the top */ + char *p = key + 2; + int plen = slen - 2; + int i; + int j; + + /* Converting hexadecimal numbered string into real key; + * Convert each two chars into one char(value). If number + * of the length is odd, add zero on the top for rounding. */ - union { - __u64 x; - unsigned char p[8]; - } val; - memset(&val, 0, sizeof(val)); + /* calculate length of the converted values(real key) */ + len = (plen + 1) / 2; + if (len > max) + invarg("\"ALGOKEY\" makes buffer overflow\n", key); - if (get_u64(&val.x, key, 16)) - invarg("\"ALGOKEY\" is invalid", key); + for (i = - (plen % 2), j = 0; j < len; i += 2, j++) { + char vbuf[3]; + char val; - len = (slen - 2) / 2; - if (len > sizeof(val)) - invarg("\"ALGOKEY\" is invalid: too large", key); + vbuf[0] = i >= 0 ? p[i] : '0'; + vbuf[1] = p[i + 1]; + vbuf[2] = '\0'; - if (len > 0) { - int i; + if (get_u8(&val, vbuf, 16)) + invarg("\"ALGOKEY\" is invalid", key); - if (len > max) - invarg("\"ALGOKEY\" makes buffer overflow\n", key); - for (i = sizeof(val.p) - 1; i >= 0; i--) { - int j = sizeof(val.p) - 1 - i; - alg->alg_key[j] = val.p[i]; - } + alg->alg_key[j] = val; } - } else { len = slen; if (len > 0) {