summaryrefslogtreecommitdiffstats
path: root/src/lib/gssapi/krb5/util_cksum.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/gssapi/krb5/util_cksum.c')
-rw-r--r--src/lib/gssapi/krb5/util_cksum.c186
1 files changed, 186 insertions, 0 deletions
diff --git a/src/lib/gssapi/krb5/util_cksum.c b/src/lib/gssapi/krb5/util_cksum.c
index b863572a7..8dcf75129 100644
--- a/src/lib/gssapi/krb5/util_cksum.c
+++ b/src/lib/gssapi/krb5/util_cksum.c
@@ -107,3 +107,189 @@ cleanup:
xfree(buf);
return code;
}
+
+krb5_error_code
+kg_make_checksum_iov_v1(krb5_context context,
+ krb5_cksumtype type,
+ size_t cksum_len,
+ krb5_keyblock *seq,
+ krb5_keyblock *enc,
+ krb5_keyusage sign_usage,
+ gss_iov_buffer_desc *iov,
+ int iov_count,
+ int toktype,
+ krb5_checksum *checksum)
+{
+ krb5_error_code code;
+ gss_iov_buffer_desc *header;
+ krb5_crypto_iov *kiov;
+ size_t kiov_count;
+ int i = 0, j;
+ size_t conf_len = 0, token_header_len;
+
+ header = kg_locate_iov(iov, iov_count, GSS_IOV_BUFFER_TYPE_HEADER);
+ assert(header != NULL);
+
+ kiov_count = 3 + iov_count;
+ kiov = (krb5_crypto_iov *)xmalloc(kiov_count * sizeof(krb5_crypto_iov));
+ if (kiov == NULL)
+ return ENOMEM;
+
+ /* Checksum over ( Header | Confounder | Data | Pad ) */
+ if (toktype == KG_TOK_WRAP_MSG)
+ conf_len = kg_confounder_size(context, (krb5_keyblock *)enc);
+
+ /* Checksum output */
+ kiov[i].flags = KRB5_CRYPTO_TYPE_CHECKSUM;
+ kiov[i].data.length = checksum->length;
+ kiov[i].data.data = xmalloc(checksum->length);
+ if (kiov[i].data.data == NULL) {
+ xfree(kiov);
+ return ENOMEM;
+ }
+ i++;
+
+ /* Header | SND_SEQ | SGN_CKSUM | Confounder */
+ token_header_len = 16 + cksum_len + conf_len;
+
+ /* Header (calculate from end because of variable length ASN.1 header) */
+ kiov[i].flags = KRB5_CRYPTO_TYPE_SIGN_ONLY;
+ kiov[i].data.length = 8;
+ kiov[i].data.data = (char *)header->buffer.value + header->buffer.length - token_header_len;
+ i++;
+
+ /* Confounder */
+ if (toktype == KG_TOK_WRAP_MSG) {
+ kiov[i].flags = KRB5_CRYPTO_TYPE_DATA;
+ kiov[i].data.length = conf_len;
+ kiov[i].data.data = (char *)header->buffer.value + header->buffer.length - conf_len;
+ i++;
+ }
+
+ for (j = 0; j < iov_count; j++) {
+ kiov[i].flags = kg_translate_flag_iov(iov[j].type);
+ kiov[i].data.length = iov[j].buffer.length;
+ kiov[i].data.data = (char *)iov[j].buffer.value;
+ i++;
+ }
+
+ code = krb5_c_make_checksum_iov(context, type, seq, sign_usage, kiov, kiov_count);
+ if (code == 0) {
+ checksum->length = kiov[0].data.length;
+ checksum->contents = (unsigned char *)kiov[0].data.data;
+ } else
+ free(kiov[0].data.data);
+
+ xfree(kiov);
+
+ return code;
+}
+
+static krb5_error_code
+checksum_iov_v3(krb5_context context,
+ krb5_cksumtype type,
+ size_t rrc,
+ krb5_keyblock *key,
+ krb5_keyusage sign_usage,
+ gss_iov_buffer_desc *iov,
+ int iov_count,
+ krb5_boolean verify,
+ krb5_boolean *valid)
+{
+ krb5_error_code code;
+ gss_iov_buffer_desc *header;
+ gss_iov_buffer_desc *trailer;
+ krb5_crypto_iov *kiov;
+ size_t kiov_count;
+ int i = 0, j;
+ unsigned int k5_checksumlen;
+
+ if (verify)
+ *valid = FALSE;
+
+ code = krb5_c_crypto_length(context, key->enctype, KRB5_CRYPTO_TYPE_CHECKSUM, &k5_checksumlen);
+ if (code != 0)
+ return code;
+
+ header = kg_locate_iov(iov, iov_count, GSS_IOV_BUFFER_TYPE_HEADER);
+ assert(header != NULL);
+
+ trailer = kg_locate_iov(iov, iov_count, GSS_IOV_BUFFER_TYPE_TRAILER);
+ assert(rrc != 0 || trailer != NULL);
+
+ if (trailer == NULL) {
+ if (rrc != k5_checksumlen)
+ return KRB5_BAD_MSIZE;
+ if (header->buffer.length != 16 + k5_checksumlen)
+ return KRB5_BAD_MSIZE;
+ } else if (trailer->buffer.length != k5_checksumlen)
+ return KRB5_BAD_MSIZE;
+
+ kiov_count = 2 + iov_count;
+ kiov = (krb5_crypto_iov *)xmalloc(kiov_count * sizeof(krb5_crypto_iov));
+ if (kiov == NULL)
+ return ENOMEM;
+
+ /* Checksum over ( Data | Header ) */
+
+ /* Data */
+ for (j = 0; j < iov_count; j++) {
+ kiov[i].flags = kg_translate_flag_iov(iov[j].type);
+ kiov[i].data.length = iov[j].buffer.length;
+ kiov[i].data.data = (char *)iov[j].buffer.value;
+ i++;
+ }
+
+ /* Header */
+ kiov[i].flags = KRB5_CRYPTO_TYPE_SIGN_ONLY;
+ kiov[i].data.length = 16;
+ kiov[i].data.data = (char *)header->buffer.value;
+ i++;
+
+ /* Checksum */
+ kiov[i].flags = KRB5_CRYPTO_TYPE_CHECKSUM;
+ if (trailer == NULL) {
+ kiov[i].data.length = header->buffer.length - 16;
+ kiov[i].data.data = (char *)header->buffer.value + 16;
+ } else {
+ kiov[i].data.length = trailer->buffer.length;
+ kiov[i].data.data = (char *)trailer->buffer.value;
+ }
+ i++;
+
+ if (verify)
+ code = krb5_c_verify_checksum_iov(context, type, key, sign_usage, kiov, kiov_count, valid);
+ else
+ code = krb5_c_make_checksum_iov(context, type, key, sign_usage, kiov, kiov_count);
+
+ xfree(kiov);
+
+ return code;
+}
+
+krb5_error_code
+kg_make_checksum_iov_v3(krb5_context context,
+ krb5_cksumtype type,
+ size_t rrc,
+ krb5_keyblock *key,
+ krb5_keyusage sign_usage,
+ gss_iov_buffer_desc *iov,
+ int iov_count)
+{
+ return checksum_iov_v3(context, type, rrc, key,
+ sign_usage, iov, iov_count, 0, NULL);
+}
+
+krb5_error_code
+kg_verify_checksum_iov_v3(krb5_context context,
+ krb5_cksumtype type,
+ size_t rrc,
+ krb5_keyblock *key,
+ krb5_keyusage sign_usage,
+ gss_iov_buffer_desc *iov,
+ int iov_count,
+ krb5_boolean *valid)
+{
+ return checksum_iov_v3(context, type, rrc, key,
+ sign_usage, iov, iov_count, 1, valid);
+}