krb5_error_code _krb5_pac_sign(krb5_context context, krb5_pac p, time_t authtime, krb5_principal principal, const krb5_keyblock *server_key, const krb5_keyblock *priv_key, krb5_data *data) { krb5_error_code ret; krb5_storage *sp = NULL, *spdata = NULL; uint32_t end; size_t server_size, priv_size; uint32_t server_offset = 0, priv_offset = 0; uint32_t server_cksumtype = 0, priv_cksumtype = 0; int i, num = 0; krb5_data logon, d; krb5_data_zero(&logon); if (p->logon_name == NULL) num++; if (p->server_checksum == NULL) num++; if (p->privsvr_checksum == NULL) num++; if (num) { void *ptr; ptr = realloc(p->pac, sizeof(*p->pac) + (sizeof(p->pac->buffers[0]) * (p->pac->numbuffers + num - 1))); if (ptr == NULL) return krb5_enomem(context); p->pac = ptr; if (p->logon_name == NULL) { p->logon_name = &p->pac->buffers[p->pac->numbuffers++]; memset(p->logon_name, 0, sizeof(*p->logon_name)); p->logon_name->type = PAC_LOGON_NAME; } if (p->server_checksum == NULL) { p->server_checksum = &p->pac->buffers[p->pac->numbuffers++]; memset(p->server_checksum, 0, sizeof(*p->server_checksum)); p->server_checksum->type = PAC_SERVER_CHECKSUM; } if (p->privsvr_checksum == NULL) { p->privsvr_checksum = &p->pac->buffers[p->pac->numbuffers++]; memset(p->privsvr_checksum, 0, sizeof(*p->privsvr_checksum)); p->privsvr_checksum->type = PAC_PRIVSVR_CHECKSUM; } } /* Calculate LOGON NAME */ ret = build_logon_name(context, authtime, principal, &logon); if (ret) goto out; /* Set lengths for checksum */ ret = pac_checksum(context, server_key, &server_cksumtype, &server_size); if (ret) goto out; ret = pac_checksum(context, priv_key, &priv_cksumtype, &priv_size); if (ret) goto out; /* Encode PAC */ sp = krb5_storage_emem(); if (sp == NULL) return krb5_enomem(context); krb5_storage_set_flags(sp, KRB5_STORAGE_BYTEORDER_LE); spdata = krb5_storage_emem(); if (spdata == NULL) { krb5_storage_free(sp); return krb5_enomem(context); } krb5_storage_set_flags(spdata, KRB5_STORAGE_BYTEORDER_LE); CHECK(ret, krb5_store_uint32(sp, p->pac->numbuffers), out); CHECK(ret, krb5_store_uint32(sp, p->pac->version), out); end = PACTYPE_SIZE + (PAC_INFO_BUFFER_SIZE * p->pac->numbuffers); for (i = 0; i < p->pac->numbuffers; i++) { uint32_t len; size_t sret; void *ptr = NULL; /* store data */ if (p->pac->buffers[i].type == PAC_SERVER_CHECKSUM) { len = server_size + 4; server_offset = end + 4; CHECK(ret, krb5_store_uint32(spdata, server_cksumtype), out); CHECK(ret, fill_zeros(context, spdata, server_size), out); } else if (p->pac->buffers[i].type == PAC_PRIVSVR_CHECKSUM) { len = priv_size + 4; priv_offset = end + 4; CHECK(ret, krb5_store_uint32(spdata, priv_cksumtype), out); CHECK(ret, fill_zeros(context, spdata, priv_size), out); } else if (p->pac->buffers[i].type == PAC_LOGON_NAME) { len = krb5_storage_write(spdata, logon.data, logon.length); if (logon.length != len) { ret = EINVAL; goto out; } } else { len = p->pac->buffers[i].buffersize; ptr = (char *)p->data.data + p->pac->buffers[i].offset_lo; sret = krb5_storage_write(spdata, ptr, len); if (sret != len) { ret = krb5_enomem(context); goto out; } /* XXX if not aligned, fill_zeros */ } /* write header */ CHECK(ret, krb5_store_uint32(sp, p->pac->buffers[i].type), out); CHECK(ret, krb5_store_uint32(sp, len), out); CHECK(ret, krb5_store_uint32(sp, end), out); CHECK(ret, krb5_store_uint32(sp, 0), out); /* advance data endpointer and align */ { int32_t e; end += len; e = ((end + PAC_ALIGNMENT - 1) / PAC_ALIGNMENT) * PAC_ALIGNMENT; if (end != e) { CHECK(ret, fill_zeros(context, spdata, e - end), out); } end = e; } } /* assert (server_offset != 0 && priv_offset != 0); */ /* export PAC */ ret = krb5_storage_to_data(spdata, &d); if (ret) { krb5_set_error_message(context, ret, N_("malloc: out of memory", "")); goto out; } ret = krb5_storage_write(sp, d.data, d.length); if (ret != d.length) { krb5_data_free(&d); ret = krb5_enomem(context); goto out; } krb5_data_free(&d); ret = krb5_storage_to_data(sp, &d); if (ret) { ret = krb5_enomem(context); goto out; } /* sign */ ret = create_checksum(context, server_key, server_cksumtype, d.data, d.length, (char *)d.data + server_offset, server_size); if (ret) { krb5_data_free(&d); goto out; } ret = create_checksum(context, priv_key, priv_cksumtype, (char *)d.data + server_offset, server_size, (char *)d.data + priv_offset, priv_size); if (ret) { krb5_data_free(&d); goto out; } /* done */ *data = d; krb5_data_free(&logon); krb5_storage_free(sp); krb5_storage_free(spdata); return 0; out: krb5_data_free(&logon); if (sp) krb5_storage_free(sp); if (spdata) krb5_storage_free(spdata); return ret; }
int et_boot_catalog(struct ISO_data_t ISO_data) { struct stat EFI_boot_file_stat; void *boot_cat_data = (void *) malloc(BLOCK_SIZE); void *boot_cat_start = boot_cat_data; void *rr = NULL; int rv = 0; char id_string[24]; FILE *boot_catalog = NULL; uint32_t boot_cat_size = 0; uint16_t unused = 0; uint16_t checksum = 0x0000; uint16_t signature = 0xAA55; uint8_t header_id = 0x01; // Always 0x01 uint8_t platform_id = 0x00; // x86 uint16_t load_segment = 0x00; uint16_t sector_count = 0x00; uint8_t boot_indicator = 0x88; // Bootable uint8_t media_type = 0x00; // No emulation uint8_t system_type = 0x00; memset(&EFI_boot_file_stat, 0, sizeof(struct stat)); memset(id_string, 0, sizeof(id_string)); memset(boot_cat_start, 0, BLOCK_SIZE); /* Move to LBA of UEFI boot image */ (ISO_data.boot_cat_LBA)++; stat(ISO_data.efi_boot_file_full, &EFI_boot_file_stat); sector_count = EFI_boot_file_stat.st_size / 512; iso9660_cp2heap(&boot_cat_data, &header_id, sizeof(uint8_t), &boot_cat_size); iso9660_cp2heap(&boot_cat_data, &platform_id, sizeof(uint8_t), &boot_cat_size); iso9660_cp2heap(&boot_cat_data, &unused, sizeof(uint16_t), &boot_cat_size); iso9660_cp2heap(&boot_cat_data, &id_string, sizeof(id_string), &boot_cat_size); iso9660_cp2heap(&boot_cat_data, &checksum, sizeof(uint16_t), &boot_cat_size); iso9660_cp2heap(&boot_cat_data, &signature, sizeof(uint16_t), &boot_cat_size); /* Calculate checksum of words so far written */ checksum = create_checksum(boot_cat_start, boot_cat_size); rr = boot_cat_data - 4; // Return back 4 bytes and write checksum boot_cat_size -= sizeof(uint16_t); // This will be counted back in next step iso9660_cp2heap(&rr, &checksum, sizeof(uint16_t), &boot_cat_size); iso9660_cp2heap(&boot_cat_data, &boot_indicator, sizeof(uint8_t), &boot_cat_size); iso9660_cp2heap(&boot_cat_data, &media_type, sizeof(uint8_t), &boot_cat_size); iso9660_cp2heap(&boot_cat_data, &load_segment, sizeof(uint16_t), &boot_cat_size); iso9660_cp2heap(&boot_cat_data, &system_type, sizeof(uint8_t), &boot_cat_size); iso9660_cp2heap(&boot_cat_data, &unused, sizeof(uint8_t), &boot_cat_size); iso9660_cp2heap(&boot_cat_data, §or_count, sizeof(uint16_t), &boot_cat_size); // Size of UEFI boot image (this will overflow because of size) iso9660_cp2heap(&boot_cat_data, &ISO_data.boot_cat_LBA, sizeof(uint32_t), &boot_cat_size); // LBA of UEFI boot image (virtual disk) boot_catalog = fopen(ISO_data.boot_cat_file, "w"); if (fwrite(boot_cat_start, 1, BLOCK_SIZE, boot_catalog) != BLOCK_SIZE) { perror("Error: et_boot_catalog()"); rv = E_IO; } fclose(boot_catalog); free(boot_cat_start); return rv; }