heimdal Don't dereference NULL in error verify_checksum error path
[samba.git] / source4 / heimdal / lib / krb5 / crypto.c
index bdcdb2ea0a13d75207d6faa58bb1ec75b6008da7..d5d9c1d9d552b864f2f61a1e15e5d0e5220489ed 100644 (file)
@@ -67,6 +67,7 @@ struct krb5_crypto_data {
 #define F_PSEUDO       16      /* not a real protocol type */
 #define F_SPECIAL      32      /* backwards */
 #define F_DISABLED     64      /* enctype/checksum disabled */
+#define F_WEAK        128      /* enctype is considered weak */
 
 struct salt_type {
     krb5_salttype type;
@@ -95,11 +96,11 @@ struct checksum_type {
     size_t blocksize;
     size_t checksumsize;
     unsigned flags;
-    krb5_enctype (*checksum)(krb5_context context,
-                            struct key_data *key,
-                            const void *buf, size_t len,
-                            unsigned usage,
-                            Checksum *csum);
+    krb5_error_code (*checksum)(krb5_context context,
+                               struct key_data *key,
+                               const void *buf, size_t len,
+                               unsigned usage,
+                               Checksum *csum);
     krb5_error_code (*verify)(krb5_context context,
                              struct key_data *key,
                              const void *buf, size_t len,
@@ -874,7 +875,7 @@ static struct key_type keytype_arcfour = {
     EVP_rc4
 };
 
-krb5_error_code KRB5_LIB_FUNCTION
+KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
 krb5_salttype_to_string (krb5_context context,
                         krb5_enctype etype,
                         krb5_salttype stype,
@@ -906,7 +907,7 @@ krb5_salttype_to_string (krb5_context context,
     return HEIM_ERR_SALTTYPE_NOSUPP;
 }
 
-krb5_error_code KRB5_LIB_FUNCTION
+KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
 krb5_string_to_salttype (krb5_context context,
                         krb5_enctype etype,
                         const char *string,
@@ -933,7 +934,7 @@ krb5_string_to_salttype (krb5_context context,
     return HEIM_ERR_SALTTYPE_NOSUPP;
 }
 
-krb5_error_code KRB5_LIB_FUNCTION
+KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
 krb5_get_pw_salt(krb5_context context,
                 krb5_const_principal principal,
                 krb5_salt *salt)
@@ -962,7 +963,7 @@ krb5_get_pw_salt(krb5_context context,
     return 0;
 }
 
-krb5_error_code KRB5_LIB_FUNCTION
+KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
 krb5_free_salt(krb5_context context,
               krb5_salt salt)
 {
@@ -970,7 +971,7 @@ krb5_free_salt(krb5_context context,
     return 0;
 }
 
-krb5_error_code KRB5_LIB_FUNCTION
+KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
 krb5_string_to_key_data (krb5_context context,
                         krb5_enctype enctype,
                         krb5_data password,
@@ -988,7 +989,7 @@ krb5_string_to_key_data (krb5_context context,
     return ret;
 }
 
-krb5_error_code KRB5_LIB_FUNCTION
+KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
 krb5_string_to_key (krb5_context context,
                    krb5_enctype enctype,
                    const char *password,
@@ -1001,7 +1002,7 @@ krb5_string_to_key (krb5_context context,
     return krb5_string_to_key_data(context, enctype, pw, principal, key);
 }
 
-krb5_error_code KRB5_LIB_FUNCTION
+KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
 krb5_string_to_key_data_salt (krb5_context context,
                              krb5_enctype enctype,
                              krb5_data password,
@@ -1020,7 +1021,7 @@ krb5_string_to_key_data_salt (krb5_context context,
  * `opaque'), returning the resulting key in `key'
  */
 
-krb5_error_code KRB5_LIB_FUNCTION
+KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
 krb5_string_to_key_data_salt_opaque (krb5_context context,
                                     krb5_enctype enctype,
                                     krb5_data password,
@@ -1052,7 +1053,7 @@ krb5_string_to_key_data_salt_opaque (krb5_context context,
  * in `key'
  */
 
-krb5_error_code KRB5_LIB_FUNCTION
+KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
 krb5_string_to_key_salt (krb5_context context,
                         krb5_enctype enctype,
                         const char *password,
@@ -1065,7 +1066,7 @@ krb5_string_to_key_salt (krb5_context context,
     return krb5_string_to_key_data_salt(context, enctype, pw, salt, key);
 }
 
-krb5_error_code KRB5_LIB_FUNCTION
+KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
 krb5_string_to_key_salt_opaque (krb5_context context,
                                krb5_enctype enctype,
                                const char *password,
@@ -1080,7 +1081,7 @@ krb5_string_to_key_salt_opaque (krb5_context context,
                                               pw, salt, opaque, key);
 }
 
-krb5_error_code KRB5_LIB_FUNCTION
+KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
 krb5_enctype_keysize(krb5_context context,
                     krb5_enctype type,
                     size_t *keysize)
@@ -1096,7 +1097,7 @@ krb5_enctype_keysize(krb5_context context,
     return 0;
 }
 
-krb5_error_code KRB5_LIB_FUNCTION
+KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
 krb5_enctype_keybits(krb5_context context,
                     krb5_enctype type,
                     size_t *keybits)
@@ -1112,7 +1113,7 @@ krb5_enctype_keybits(krb5_context context,
     return 0;
 }
 
-krb5_error_code KRB5_LIB_FUNCTION
+KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
 krb5_generate_random_keyblock(krb5_context context,
                              krb5_enctype type,
                              krb5_keyblock *key)
@@ -1439,7 +1440,7 @@ hmac(krb5_context context,
     return 0;
 }
 
-krb5_error_code KRB5_LIB_FUNCTION
+KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
 krb5_hmac(krb5_context context,
          krb5_cksumtype cktype,
          const void *data,
@@ -1495,6 +1496,8 @@ SP_HMAC_SHA1_checksum(krb5_context context,
 
 /*
  * checksum according to section 5. of draft-brezak-win2k-krb-rc4-hmac-03.txt
+ *
+ * This function made available to PAC routines
  */
 
 static krb5_error_code
@@ -1546,6 +1549,36 @@ HMAC_MD5_checksum(krb5_context context,
     return 0;
 }
 
+/* HMAC-MD5 checksum over any key (needed for the PAC routines) */
+krb5_error_code
+HMAC_MD5_any_checksum(krb5_context context,
+                     const krb5_keyblock *key,
+                     const void *data,
+                     size_t len,
+                     unsigned usage,
+                     Checksum *result)
+{
+       krb5_error_code ret;
+       struct key_data local_key;
+       ret = krb5_copy_keyblock(context, key, &local_key.key);
+       if (ret)
+           return ret;
+
+       local_key.schedule = NULL;
+       ret = krb5_data_alloc (&result->checksum, 16);
+       if (ret)
+           return ret;
+
+       result->cksumtype = CKSUMTYPE_HMAC_MD5;
+       ret = HMAC_MD5_checksum(context, &local_key, data, len, usage, result);
+
+       if (ret)
+               krb5_data_free(&result->checksum);
+
+       krb5_free_keyblock(context, local_key.key);
+       return ret;
+}
+
 static struct checksum_type checksum_none = {
     CKSUMTYPE_NONE,
     "none",
@@ -1785,7 +1818,7 @@ arcfour_checksum_p(struct checksum_type *ct, krb5_crypto crypto)
        (crypto->key.key->keytype == KEYTYPE_ARCFOUR);
 }
 
-krb5_error_code KRB5_LIB_FUNCTION
+KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
 krb5_create_checksum(krb5_context context,
                     krb5_crypto crypto,
                     krb5_key_usage usage,
@@ -1846,24 +1879,30 @@ verify_checksum(krb5_context context,
     }
     if(ct->checksumsize != cksum->checksum.length) {
        krb5_clear_error_message (context);
+       krb5_set_error_message(context, KRB5KRB_AP_ERR_BAD_INTEGRITY,
+                              N_("Decrypt integrity check failed for checksum type %s, "
+                                 "length was %u, expected %u", ""),
+                              ct->name, (unsigned)cksum->checksum.length,
+                              (unsigned)ct->checksumsize);
+
        return KRB5KRB_AP_ERR_BAD_INTEGRITY; /* XXX */
     }
     keyed_checksum = (ct->flags & F_KEYED) != 0;
     if(keyed_checksum) {
        struct checksum_type *kct;
        if (crypto == NULL) {
-           krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
-                                   N_("Checksum type %s is keyed but no "
-                                      "crypto context (key) was passed in", ""),
-                                   ct->name);
+           krb5_set_error_message(context, KRB5_PROG_SUMTYPE_NOSUPP,
+                                  N_("Checksum type %s is keyed but no "
+                                     "crypto context (key) was passed in", ""),
+                                  ct->name);
            return KRB5_PROG_SUMTYPE_NOSUPP; /* XXX */
        }
        kct = crypto->et->keyed_checksum;
        if (kct != NULL && kct->type != ct->type) {
-           krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
-                                   N_("Checksum type %s is keyed, but "
-                                      "the key type %s passed didnt have that checksum "
-                                      "type as the keyed type", ""),
+           krb5_set_error_message(context, KRB5_PROG_SUMTYPE_NOSUPP,
+                                  N_("Checksum type %s is keyed, but "
+                                     "the key type %s passed didnt have that checksum "
+                                     "type as the keyed type", ""),
                                    ct->name, crypto->et->name);
            return KRB5_PROG_SUMTYPE_NOSUPP; /* XXX */
        }
@@ -1873,8 +1912,21 @@ verify_checksum(krb5_context context,
            return ret;
     } else
        dkey = NULL;
-    if(ct->verify)
-       return (*ct->verify)(context, dkey, data, len, usage, cksum);
+
+    /*
+     * If checksum have a verify function, lets use that instead of
+     * calling ->checksum and then compare result.
+     */
+
+    if(ct->verify) {
+       ret = (*ct->verify)(context, dkey, data, len, usage, cksum);
+       if (ret)
+           krb5_set_error_message(context, ret, 
+                                  N_("Decrypt integrity check failed for checksum "
+                                     "type %s, key type %s", ""),
+                                  ct->name, crypto->et->name);
+       return ret;
+    }
 
     ret = krb5_data_alloc (&c.checksum, ct->checksumsize);
     if (ret)
@@ -1890,6 +1942,10 @@ verify_checksum(krb5_context context,
        ct_memcmp(c.checksum.data, cksum->checksum.data, c.checksum.length)) {
        krb5_clear_error_message (context);
        ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
+       krb5_set_error_message(context, ret,
+                              N_("Decrypt integrity check failed for checksum "
+                                 "type %s, key type %s", ""),
+                              ct->name, crypto ? crypto->et->name : "(unkeyed)");
     } else {
        ret = 0;
     }
@@ -1897,7 +1953,7 @@ verify_checksum(krb5_context context,
     return ret;
 }
 
-krb5_error_code KRB5_LIB_FUNCTION
+KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
 krb5_verify_checksum(krb5_context context,
                     krb5_crypto crypto,
                     krb5_key_usage usage,
@@ -1926,7 +1982,7 @@ krb5_verify_checksum(krb5_context context,
                           data, len, cksum);
 }
 
-krb5_error_code KRB5_LIB_FUNCTION
+KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
 krb5_crypto_get_checksum_type(krb5_context context,
                               krb5_crypto crypto,
                              krb5_cksumtype *type)
@@ -1951,7 +2007,7 @@ krb5_crypto_get_checksum_type(krb5_context context,
 }
 
 
-krb5_error_code KRB5_LIB_FUNCTION
+KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
 krb5_checksumsize(krb5_context context,
                  krb5_cksumtype type,
                  size_t *size)
@@ -1967,7 +2023,7 @@ krb5_checksumsize(krb5_context context,
     return 0;
 }
 
-krb5_boolean KRB5_LIB_FUNCTION
+KRB5_LIB_FUNCTION krb5_boolean KRB5_LIB_CALL
 krb5_checksum_is_keyed(krb5_context context,
                       krb5_cksumtype type)
 {
@@ -1982,7 +2038,7 @@ krb5_checksum_is_keyed(krb5_context context,
     return ct->flags & F_KEYED;
 }
 
-krb5_boolean KRB5_LIB_FUNCTION
+KRB5_LIB_FUNCTION krb5_boolean KRB5_LIB_CALL
 krb5_checksum_is_collision_proof(krb5_context context,
                                 krb5_cksumtype type)
 {
@@ -1997,7 +2053,7 @@ krb5_checksum_is_collision_proof(krb5_context context,
     return ct->flags & F_CPROOF;
 }
 
-krb5_error_code KRB5_LIB_FUNCTION
+KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
 krb5_checksum_disable(krb5_context context,
                      krb5_cksumtype type)
 {
@@ -2043,13 +2099,13 @@ evp_encrypt(krb5_context context,
     c = encryptp ? &ctx->ectx : &ctx->dctx;
     if (ivec == NULL) {
        /* alloca ? */
-       size_t len = EVP_CIPHER_CTX_iv_length(c);
-       void *loiv = malloc(len);
+       size_t len2 = EVP_CIPHER_CTX_iv_length(c);
+       void *loiv = malloc(len2);
        if (loiv == NULL) {
            krb5_clear_error_message(context);
            return ENOMEM;
        }
-       memset(loiv, 0, len);
+       memset(loiv, 0, len2);
        EVP_CipherInit_ex(c, NULL, NULL, NULL, loiv, -1);
        free(loiv);
     } else
@@ -2058,7 +2114,7 @@ evp_encrypt(krb5_context context,
     return 0;
 }
 
-static const char zero_ivec[EVP_MAX_BLOCK_LENGTH] = { 0 };
+static const unsigned char zero_ivec[EVP_MAX_BLOCK_LENGTH] = { 0 };
 
 static krb5_error_code
 evp_encrypt_cts(krb5_context context,
@@ -2386,7 +2442,6 @@ usage2arcfour (krb5_context context, unsigned *usage)
 {
     switch (*usage) {
     case KRB5_KU_AS_REP_ENC_PART : /* 3 */
-    case KRB5_KU_TGS_REP_ENC_PART_SUB_KEY : /* 9 */
        *usage = 8;
        return 0;
     case KRB5_KU_USAGE_SEAL :  /* 22 */
@@ -2613,7 +2668,7 @@ static struct encryption_type enctype_des_cbc_crc = {
     &keytype_des,
     &checksum_crc32,
     NULL,
-    F_DISABLED,
+    F_DISABLED|F_WEAK,
     evp_des_encrypt_key_ivec,
     0,
     NULL
@@ -2627,7 +2682,7 @@ static struct encryption_type enctype_des_cbc_md4 = {
     &keytype_des,
     &checksum_rsa_md4,
     &checksum_rsa_md4_des,
-    F_DISABLED,
+    F_DISABLED|F_WEAK,
     evp_des_encrypt_null_ivec,
     0,
     NULL
@@ -2641,7 +2696,7 @@ static struct encryption_type enctype_des_cbc_md5 = {
     &keytype_des,
     &checksum_rsa_md5,
     &checksum_rsa_md5_des,
-    F_DISABLED,
+    F_DISABLED|F_WEAK,
     evp_des_encrypt_null_ivec,
     0,
     NULL
@@ -2655,7 +2710,7 @@ static struct encryption_type enctype_des_cbc_none = {
     &keytype_des,
     &checksum_none,
     NULL,
-    F_PSEUDO|F_DISABLED,
+    F_PSEUDO|F_DISABLED|F_WEAK,
     evp_des_encrypt_null_ivec,
     0,
     NULL
@@ -2669,7 +2724,7 @@ static struct encryption_type enctype_des_cfb64_none = {
     &keytype_des_old,
     &checksum_none,
     NULL,
-    F_PSEUDO|F_DISABLED,
+    F_PSEUDO|F_DISABLED|F_WEAK,
     DES_CFB64_encrypt_null_ivec,
     0,
     NULL
@@ -2683,7 +2738,7 @@ static struct encryption_type enctype_des_pcbc_none = {
     &keytype_des_old,
     &checksum_none,
     NULL,
-    F_PSEUDO|F_DISABLED,
+    F_PSEUDO|F_DISABLED|F_WEAK,
     DES_PCBC_encrypt_key_ivec,
     0,
     NULL
@@ -2725,7 +2780,7 @@ _find_enctype(krb5_enctype type)
 }
 
 
-krb5_error_code KRB5_LIB_FUNCTION
+KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
 krb5_enctype_to_string(krb5_context context,
                       krb5_enctype etype,
                       char **string)
@@ -2747,7 +2802,7 @@ krb5_enctype_to_string(krb5_context context,
     return 0;
 }
 
-krb5_error_code KRB5_LIB_FUNCTION
+KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
 krb5_string_to_enctype(krb5_context context,
                       const char *string,
                       krb5_enctype *etype)
@@ -2764,7 +2819,7 @@ krb5_string_to_enctype(krb5_context context,
     return KRB5_PROG_ETYPE_NOSUPP;
 }
 
-krb5_error_code KRB5_LIB_FUNCTION
+KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
 krb5_enctype_to_keytype(krb5_context context,
                        krb5_enctype etype,
                        krb5_keytype *keytype)
@@ -2780,7 +2835,7 @@ krb5_enctype_to_keytype(krb5_context context,
     return 0;
 }
 
-krb5_error_code KRB5_LIB_FUNCTION
+KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
 krb5_enctype_valid(krb5_context context,
                   krb5_enctype etype)
 {
@@ -2813,7 +2868,7 @@ krb5_enctype_valid(krb5_context context,
  */
 
 
-krb5_error_code KRB5_LIB_FUNCTION
+KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
 krb5_cksumtype_to_enctype(krb5_context context,
                          krb5_cksumtype ctype,
                          krb5_enctype *etype)
@@ -2838,7 +2893,7 @@ krb5_cksumtype_to_enctype(krb5_context context,
 }
 
 
-krb5_error_code KRB5_LIB_FUNCTION
+KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
 krb5_cksumtype_valid(krb5_context context,
                     krb5_cksumtype ctype)
 {
@@ -3144,8 +3199,14 @@ decrypt_internal(krb5_context context,
        krb5_clear_error_message(context);
        return KRB5_BAD_MSIZE;
     }
-
     checksum_sz = CHECKSUMSIZE(et->checksum);
+    if (len < checksum_sz + et->confoundersize) {
+       krb5_set_error_message(context, KRB5_BAD_MSIZE,
+                              N_("Encrypted data shorter then "
+                                 "checksum + confunder", ""));
+       return KRB5_BAD_MSIZE;
+    }
+
     p = malloc(len);
     if(len != 0 && p == NULL) {
        krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
@@ -3207,6 +3268,12 @@ decrypt_internal_special(krb5_context context,
        krb5_clear_error_message(context);
        return KRB5_BAD_MSIZE;
     }
+    if (len < cksum_sz + et->confoundersize) {
+       krb5_set_error_message(context, KRB5_BAD_MSIZE,
+                              N_("Encrypted data shorter then "
+                                 "checksum + confunder", ""));
+       return KRB5_BAD_MSIZE;
+    }
 
     p = malloc (len);
     if (p == NULL) {
@@ -3266,7 +3333,7 @@ find_iv(krb5_crypto_iov *data, int num_data, int type)
  * 4. KRB5_CRYPTO_TYPE_TRAILER
  */
 
-krb5_error_code KRB5_LIB_FUNCTION
+KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
 krb5_encrypt_iov_ivec(krb5_context context,
                      krb5_crypto crypto,
                      unsigned usage,
@@ -3459,7 +3526,7 @@ krb5_encrypt_iov_ivec(krb5_context context,
  *  size as the input data or shorter.
  */
 
-krb5_error_code KRB5_LIB_FUNCTION
+KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
 krb5_decrypt_iov_ivec(krb5_context context,
                      krb5_crypto crypto,
                      unsigned usage,
@@ -3607,7 +3674,7 @@ krb5_decrypt_iov_ivec(krb5_context context,
  * @ingroup krb5_crypto
  */
 
-krb5_error_code KRB5_LIB_FUNCTION
+KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
 krb5_create_checksum_iov(krb5_context context,
                         krb5_crypto crypto,
                         unsigned usage,
@@ -3690,7 +3757,7 @@ krb5_create_checksum_iov(krb5_context context,
  * @ingroup krb5_crypto
  */
 
-krb5_error_code KRB5_LIB_FUNCTION
+KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
 krb5_verify_checksum_iov(krb5_context context,
                         krb5_crypto crypto,
                         unsigned usage,
@@ -3752,7 +3819,7 @@ krb5_verify_checksum_iov(krb5_context context,
 }
 
 
-krb5_error_code KRB5_LIB_FUNCTION
+KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
 krb5_crypto_length(krb5_context context,
                   krb5_crypto crypto,
                   int type,
@@ -3796,7 +3863,7 @@ krb5_crypto_length(krb5_context context,
 }
 
 
-krb5_error_code KRB5_LIB_FUNCTION
+KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
 krb5_crypto_length_iov(krb5_context context,
                       krb5_crypto crypto,
                       krb5_crypto_iov *data,
@@ -3816,7 +3883,7 @@ krb5_crypto_length_iov(krb5_context context,
 }
 
 
-krb5_error_code KRB5_LIB_FUNCTION
+KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
 krb5_encrypt_ivec(krb5_context context,
                  krb5_crypto crypto,
                  unsigned usage,
@@ -3835,7 +3902,7 @@ krb5_encrypt_ivec(krb5_context context,
        return encrypt_internal(context, crypto, data, len, result, ivec);
 }
 
-krb5_error_code KRB5_LIB_FUNCTION
+KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
 krb5_encrypt(krb5_context context,
             krb5_crypto crypto,
             unsigned usage,
@@ -3846,7 +3913,7 @@ krb5_encrypt(krb5_context context,
     return krb5_encrypt_ivec(context, crypto, usage, data, len, result, NULL);
 }
 
-krb5_error_code KRB5_LIB_FUNCTION
+KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
 krb5_encrypt_EncryptedData(krb5_context context,
                           krb5_crypto crypto,
                           unsigned usage,
@@ -3864,7 +3931,7 @@ krb5_encrypt_EncryptedData(krb5_context context,
     return krb5_encrypt(context, crypto, usage, data, len, &result->cipher);
 }
 
-krb5_error_code KRB5_LIB_FUNCTION
+KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
 krb5_decrypt_ivec(krb5_context context,
                  krb5_crypto crypto,
                  unsigned usage,
@@ -3883,7 +3950,7 @@ krb5_decrypt_ivec(krb5_context context,
        return decrypt_internal(context, crypto, data, len, result, ivec);
 }
 
-krb5_error_code KRB5_LIB_FUNCTION
+KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
 krb5_decrypt(krb5_context context,
             krb5_crypto crypto,
             unsigned usage,
@@ -3895,7 +3962,7 @@ krb5_decrypt(krb5_context context,
                              NULL);
 }
 
-krb5_error_code KRB5_LIB_FUNCTION
+KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
 krb5_decrypt_EncryptedData(krb5_context context,
                           krb5_crypto crypto,
                           unsigned usage,
@@ -3937,6 +4004,7 @@ seed_something(void)
     /* Calling RAND_status() will try to use /dev/urandom if it exists so
        we do not have to deal with it. */
     if (RAND_status() != 1) {
+#ifndef _WIN32
        krb5_context context;
        const char *p;
 
@@ -3948,6 +4016,10 @@ seed_something(void)
                RAND_egd_bytes(p, ENTROPY_NEEDED);
            krb5_free_context(context);
        }
+#else
+       /* TODO: Once a Windows CryptoAPI RAND method is defined, we
+          can use that and failover to another method. */
+#endif
     }
 
     if (RAND_status() == 1)    {
@@ -3960,7 +4032,7 @@ seed_something(void)
        return -1;
 }
 
-void KRB5_LIB_FUNCTION
+KRB5_LIB_FUNCTION void KRB5_LIB_CALL
 krb5_generate_random_block(void *buf, size_t len)
 {
     static int rng_initialized = 0;
@@ -3974,7 +4046,7 @@ krb5_generate_random_block(void *buf, size_t len)
        rng_initialized = 1;
     }
     HEIMDAL_MUTEX_unlock(&crypto_mutex);
-    if (RAND_bytes(buf, len) != 1)
+    if (RAND_bytes(buf, len) <= 0)
        krb5_abortx(NULL, "Failed to generate random block");
 }
 
@@ -4084,7 +4156,7 @@ _new_derived_key(krb5_crypto crypto, unsigned usage)
     return &d->key;
 }
 
-krb5_error_code KRB5_LIB_FUNCTION
+KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
 krb5_derive_key(krb5_context context,
                const krb5_keyblock *key,
                krb5_enctype etype,
@@ -4163,7 +4235,7 @@ _get_derived_key(krb5_context context,
  * @ingroup krb5_crypto
  */
 
-krb5_error_code KRB5_LIB_FUNCTION
+KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
 krb5_crypto_init(krb5_context context,
                 const krb5_keyblock *key,
                 krb5_enctype etype,
@@ -4245,7 +4317,7 @@ free_key_usage(krb5_context context, struct key_usage *ku,
  * @ingroup krb5_crypto
  */
 
-krb5_error_code KRB5_LIB_FUNCTION
+KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
 krb5_crypto_destroy(krb5_context context,
                    krb5_crypto crypto)
 {
@@ -4271,7 +4343,7 @@ krb5_crypto_destroy(krb5_context context,
  * @ingroup krb5_crypto
  */
 
-krb5_error_code KRB5_LIB_FUNCTION
+KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
 krb5_crypto_getblocksize(krb5_context context,
                         krb5_crypto crypto,
                         size_t *blocksize)
@@ -4292,7 +4364,7 @@ krb5_crypto_getblocksize(krb5_context context,
  * @ingroup krb5_crypto
  */
 
-krb5_error_code KRB5_LIB_FUNCTION
+KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
 krb5_crypto_getenctype(krb5_context context,
                       krb5_crypto crypto,
                       krb5_enctype *enctype)
@@ -4313,7 +4385,7 @@ krb5_crypto_getenctype(krb5_context context,
  * @ingroup krb5_crypto
  */
 
-krb5_error_code KRB5_LIB_FUNCTION
+KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
 krb5_crypto_getpadsize(krb5_context context,
                        krb5_crypto crypto,
                        size_t *padsize)
@@ -4334,7 +4406,7 @@ krb5_crypto_getpadsize(krb5_context context,
  * @ingroup krb5_crypto
  */
 
-krb5_error_code KRB5_LIB_FUNCTION
+KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
 krb5_crypto_getconfoundersize(krb5_context context,
                               krb5_crypto crypto,
                               size_t *confoundersize)
@@ -4355,7 +4427,7 @@ krb5_crypto_getconfoundersize(krb5_context context,
  * @ingroup krb5_crypto
  */
 
-krb5_error_code KRB5_LIB_FUNCTION
+KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
 krb5_enctype_disable(krb5_context context,
                     krb5_enctype enctype)
 {
@@ -4382,7 +4454,7 @@ krb5_enctype_disable(krb5_context context,
  * @ingroup krb5_crypto
  */
 
-krb5_error_code KRB5_LIB_FUNCTION
+KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
 krb5_enctype_enable(krb5_context context,
                    krb5_enctype enctype)
 {
@@ -4398,8 +4470,35 @@ krb5_enctype_enable(krb5_context context,
     return 0;
 }
 
+/**
+ * Enable or disable all weak encryption types
+ *
+ * @param context Kerberos 5 context
+ * @param enable true to enable, false to disable
+ *
+ * @return Return an error code or 0.
+ *
+ * @ingroup krb5_crypto
+ */
+
+KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
+krb5_allow_weak_crypto(krb5_context context,
+                      krb5_boolean enable)
+{
+    int i;
+
+    for(i = 0; i < num_etypes; i++)
+       if(etypes[i]->flags & F_WEAK) {
+           if(enable)
+               etypes[i]->flags &= ~F_DISABLED;
+           else
+               etypes[i]->flags |= F_DISABLED;
+       }
+    return 0;
+}
+
 
-krb5_error_code KRB5_LIB_FUNCTION
+KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
 krb5_string_to_key_derived(krb5_context context,
                           const void *str,
                           size_t len,
@@ -4571,7 +4670,7 @@ krb5_crypto_overhead (krb5_context context, krb5_crypto crypto)
  * @ingroup krb5_crypto
  */
 
-krb5_error_code KRB5_LIB_FUNCTION
+KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
 krb5_random_to_key(krb5_context context,
                   krb5_enctype type,
                   const void *data,
@@ -4863,7 +4962,7 @@ _krb5_pk_kdf(krb5_context context,
 }
 
 
-krb5_error_code KRB5_LIB_FUNCTION
+KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
 krb5_crypto_prf_length(krb5_context context,
                       krb5_enctype type,
                       size_t *length)
@@ -4881,7 +4980,7 @@ krb5_crypto_prf_length(krb5_context context,
     return 0;
 }
 
-krb5_error_code KRB5_LIB_FUNCTION
+KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
 krb5_crypto_prf(krb5_context context,
                const krb5_crypto crypto,
                const krb5_data *input,
@@ -4972,7 +5071,7 @@ krb5_crypto_prfplus(krb5_context context,
  * @ingroup krb5_crypto
  */
 
-krb5_error_code KRB5_LIB_FUNCTION
+KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
 krb5_crypto_fx_cf2(krb5_context context,
                   const krb5_crypto crypto1,
                   const krb5_crypto crypto2,
@@ -5020,12 +5119,18 @@ krb5_crypto_fx_cf2(krb5_context context,
 
 #ifndef HEIMDAL_SMALLER
 
-krb5_error_code KRB5_LIB_FUNCTION
+/**
+ * Deprecated: keytypes doesn't exists, they are really enctypes.
+ *
+ * @ingroup krb5_deprecated
+ */
+
+KRB5_DEPRECATED
+KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
 krb5_keytype_to_enctypes (krb5_context context,
                          krb5_keytype keytype,
                          unsigned *len,
                          krb5_enctype **val)
-    KRB5_DEPRECATED
 {
     int i;
     unsigned n = 0;
@@ -5060,12 +5165,18 @@ krb5_keytype_to_enctypes (krb5_context context,
     return 0;
 }
 
+/**
+ * Deprecated: keytypes doesn't exists, they are really enctypes.
+ *
+ * @ingroup krb5_deprecated
+ */
+
 /* if two enctypes have compatible keys */
-krb5_boolean KRB5_LIB_FUNCTION
+KRB5_DEPRECATED
+KRB5_LIB_FUNCTION krb5_boolean KRB5_LIB_CALL
 krb5_enctypes_compatible_keys(krb5_context context,
                              krb5_enctype etype1,
                              krb5_enctype etype2)
-    KRB5_DEPRECATED
 {
     struct encryption_type *e1 = _find_enctype(etype1);
     struct encryption_type *e2 = _find_enctype(etype2);