fr_md5_ctx_free(&md5_ctx);
}
-/** Encode Tunnel-Password attributes when sending them out on the wire
- *
- * int *pwlen is updated to the new length of the encrypted
- * password - a multiple of 16 bytes.
- *
- * This is per RFC-2868 which adds a two char SALT to the initial intermediate
- * value MD5 hash.
- */
-int fr_radius_encode_tunnel_password(char *passwd, size_t *pwlen, char const *secret, uint8_t const *vector)
-{
- uint8_t buffer[RADIUS_AUTH_VECTOR_LENGTH + FR_MAX_STRING_LEN + 3];
- unsigned char digest[RADIUS_AUTH_VECTOR_LENGTH];
- char *salt;
- int i, n, secretlen;
- unsigned len, n2;
-
- len = *pwlen;
-
- if (len > 127) len = 127;
-
- /*
- * Shift the password 3 positions right to place a salt and original
- * length, tag will be added automatically on packet send.
- */
- for (n = len ; n >= 0 ; n--) passwd[n + 3] = passwd[n];
- salt = passwd;
- passwd += 2;
-
- /*
- * save original password length as first password character;
- */
- *passwd = len;
- len += 1;
-
-
- /*
- * Generate salt. The RFC's say:
- *
- * The high bit of salt[0] must be set, each salt in a
- * packet should be unique, and they should be random
- *
- * So, we set the high bit, add in a counter, and then
- * add in some CSPRNG data. should be OK..
- */
- salt[0] = (0x80 | (((salt_offset++) & 0x0f) << 3) | (fr_rand() & 0x07));
- salt[1] = fr_rand();
-
- /*
- * Padd password to multiple of AUTH_PASS_LEN bytes.
- */
- n = len % AUTH_PASS_LEN;
- if (n) {
- n = AUTH_PASS_LEN - n;
- for (; n > 0; n--, len++) passwd[len] = 0;
- }
- /* set new password length */
- *pwlen = len + 2;
-
- /*
- * Use the secret to setup the decryption digest
- */
- secretlen = talloc_array_length(secret) - 1;
- memcpy(buffer, secret, secretlen);
-
- for (n2 = 0; n2 < len; n2 +=AUTH_PASS_LEN) {
- if (!n2) {
- memcpy(buffer + secretlen, vector, RADIUS_AUTH_VECTOR_LENGTH);
- memcpy(buffer + secretlen + RADIUS_AUTH_VECTOR_LENGTH, salt, 2);
- fr_md5_calc(digest, buffer, secretlen + RADIUS_AUTH_VECTOR_LENGTH + 2);
- } else {
- memcpy(buffer + secretlen, passwd + n2 - AUTH_PASS_LEN, AUTH_PASS_LEN);
- fr_md5_calc(digest, buffer, secretlen + AUTH_PASS_LEN);
- }
- for (i = 0; i < AUTH_PASS_LEN; i++) passwd[i + n2] ^= digest[i];
- }
- passwd[n2] = 0;
- return 0;
-}
-
-/** Encode password
- *
- * We assume that the passwd buffer passed is big enough.
- * RFC2138 says the password is max 128 chars, so the size
- * of the passwd buffer must be at least 129 characters.
- * Preferably it's just FR_MAX_STRING_LEN.
- *
- * int *pwlen is updated to the new length of the encrypted
- * password - a multiple of 16 bytes.
- */
-int fr_radius_encode_password(char *passwd, size_t *pwlen, char const *secret, uint8_t const *vector)
-{
- fr_md5_ctx_t *md5_ctx, *md5_ctx_old;
- uint8_t digest[RADIUS_AUTH_VECTOR_LENGTH];
- int i, n, secretlen;
- int len;
-
- /*
- * RFC maximum is 128 bytes.
- *
- * If length is zero, pad it out with zeros.
- *
- * If the length isn't aligned to 16 bytes,
- * zero out the extra data.
- */
- len = *pwlen;
-
- if (len > 128) len = 128;
-
- if (len == 0) {
- memset(passwd, 0, AUTH_PASS_LEN);
- len = AUTH_PASS_LEN;
- } else if ((len % AUTH_PASS_LEN) != 0) {
- memset(&passwd[len], 0, AUTH_PASS_LEN - (len % AUTH_PASS_LEN));
- len += AUTH_PASS_LEN - (len % AUTH_PASS_LEN);
- }
- *pwlen = len;
-
- /*
- * Use the secret to setup the decryption digest
- */
- secretlen = talloc_array_length(secret) - 1;
-
- md5_ctx = fr_md5_ctx_alloc(false);
- md5_ctx_old = fr_md5_ctx_alloc(true);
-
- fr_md5_update(md5_ctx, (uint8_t const *) secret, secretlen);
- fr_md5_ctx_copy(md5_ctx_old, md5_ctx); /* save intermediate work */
-
- /*
- * Encrypt it in place. Don't bother checking
- * len, as we've ensured above that it's OK.
- */
- for (n = 0; n < len; n += AUTH_PASS_LEN) {
- if (n == 0) {
- fr_md5_update(md5_ctx, vector, AUTH_PASS_LEN);
- fr_md5_final(digest, md5_ctx);
- } else {
- fr_md5_ctx_copy(md5_ctx, md5_ctx_old);
- fr_md5_update(md5_ctx, (uint8_t *) passwd + n - AUTH_PASS_LEN, AUTH_PASS_LEN);
- fr_md5_final(digest, md5_ctx);
- }
-
- for (i = 0; i < AUTH_PASS_LEN; i++) passwd[i + n] ^= digest[i];
- }
-
- fr_md5_ctx_free(&md5_ctx);
- fr_md5_ctx_free(&md5_ctx_old);
-
- return 0;
-}
static void encode_password(uint8_t *out, ssize_t *outlen, uint8_t const *input, size_t inlen,
char const *secret, uint8_t const *vector)