static off_t get_sig_offset(xar_t x) { off_t signedDataOffset = 0; xar_signature_t sig = xar_signature_first(x); xar_signature_copy_signed_data(sig,NULL,NULL,NULL,NULL,&signedDataOffset); signedDataOffset += xar_get_heap_offset(x); return signedDataOffset; }
bool InstallChecker::verifyPackage( const QString &filePath, bool ) { QProcess proc; proc.start( "hdiutil", QStringList() << "verify" << filePath ); proc.waitForFinished(); if( proc.exitCode() ) return false; QString path = mountPackage( filePath ); if( path.isEmpty() ) return false; xar_t xar = xar_open( path.toUtf8().constData(), 0 ); if( !xar ) return false; QSslCertificate cert; xar_signature_t sig = xar_signature_first( xar ); int32_t count = xar_signature_get_x509certificate_count( sig ); for( int32_t i = 0; i < count; ++i ) { uint32_t size = 0; const uint8_t *data = 0; if( xar_signature_get_x509certificate_data( sig, i, &data, &size ) ) continue; QSslCertificate c( QByteArray( (const char*)data, size ), QSsl::Der ); #if QT_VERSION >= 0x050000 QString cn = c.subjectInfo( QSslCertificate::CommonName ).value(0); #else QString cn = c.subjectInfo( QSslCertificate::CommonName ); #endif if( cn == "Estonian Informatics Centre" || cn == "Developer ID Installer: Riigi Infosüsteemi Amet" ) cert = c; } if( cert.isNull() ) { xar_close( xar ); return false; } uint8_t *data = 0, *signature = 0; uint32_t dataSize = 0, signatureSize = 0; off_t offset = 0; if( xar_signature_copy_signed_data( sig, &data, &dataSize, &signature, &signatureSize, &offset ) ) { xar_close( xar ); return false; } int result = RSA_verify( NID_sha1, data, dataSize, signature, signatureSize, (RSA*)cert.publicKey().handle() ); xar_close( xar ); free( data ); free( signature ); return result; }
/* belated_sign Prepare a previously unsigned archive for signing by creating a signature placeholder and inserting the certificates. Since libxar is currently not capable of doing this directly, we have to create a new xar archive, copy all the files and options from the current archive, and sign the new archive */ static void belated_sign(const char *filename) { xar_t x = xar_open(filename, READ); if ( x == NULL ) { fprintf(stderr, "Could not open archive %s!\n", filename); exit(1); } xar_signature_t sig = xar_signature_first(x); if ( sig ) { fprintf(stderr, "Archive has already been signed. Use --replace-sign instead.\n"); exit(E_SIGEXISTS); } xar_close(x); replace_sign(filename); }
static void extract_certs(char *filename, char *cert_base_path) { xar_signature_t sig; xar_t x; int32_t count; int i; const uint8_t *cert_data; uint32_t cert_len; FILE *file; char *cert_path; // open xar, get signature x = xar_open(filename, READ); if ( x == NULL ) { fprintf(stderr, "Could not open %s to extract certificates!\n", filename); exit(1); } sig = xar_signature_first(x); if ( !sig ) { fprintf(stderr, "No signatures found to extract data from.\n"); exit(E_NOSIG); } // iterate through all certificates associated with that signature, write them to disk count = xar_signature_get_x509certificate_count(sig); if (!count) { fprintf(stderr, "Signature bears no certificates. Odd.\n"); exit(1); } for (i=0; i<count; i++) { xar_signature_get_x509certificate_data(sig, i, &cert_data, &cert_len); asprintf(&cert_path, "%s/cert%02i", cert_base_path, i); file = fopen(cert_path, "w"); if (!file) { fprintf(stderr, "Could not save certificate %i to %s.\n", i, cert_path); exit(1); } int n = fwrite(cert_data, cert_len, 1, file); if (n < 0) { fprintf(stderr, "Failed to write certificate to %s (fwrite() returned %i)!\n", cert_path, n); exit(1); } fclose(file); free(cert_path); } // clean up xar_close(x); }
static void extract_data_to_sign(const char *filename) { xar_signature_t sig; off_t signatureOffset; FILE *file; xar_t x; int i; uint32_t dataToSignOffset = 0; uint32_t dataToSignSize = 0; char *buffer = NULL; const char *value; // find signature stub x = xar_open(filename, READ); if ( x == NULL ) { fprintf(stderr, "Could not open %s to extract data to sign!\n", filename); exit(1); } sig = xar_signature_first(x); if ( !sig ) { fprintf(stderr, "No signatures found to extract data from.\n"); exit(E_NOSIG); } // locate data to sign if( 0 != xar_prop_get((xar_file_t)x, "checksum/offset" ,&value) ){ fprintf(stderr, "Could not locate checksum/offset in archive.\n"); exit(1); } dataToSignOffset = xar_get_heap_offset(x); dataToSignOffset += strtoull(value, (char **)NULL, 10); if( 0 != xar_prop_get((xar_file_t)x, "checksum/size" ,&value) ){ fprintf(stderr, "Could not locate checksum/size in archive.\n"); exit(1); } dataToSignSize = strtoull(value, (char **)NULL, 10); // get signature offset (inject signature here) xar_signature_copy_signed_data(sig, NULL, NULL, NULL, NULL, &signatureOffset); signatureOffset += xar_get_heap_offset(x); xar_close(x); // now get data to be signed, using offset and size file = fopen(filename, "r"); if (!file) { fprintf(stderr, "Could not open %s for reading data to sign!\n", filename); exit(1); } fseek(file, dataToSignOffset, SEEK_SET); buffer = malloc(dataToSignSize); i = fread(buffer, dataToSignSize, 1, file); if (i != 1) { fprintf(stderr, "Failed to read data to sign from %s!\n", filename); exit(1); } fclose(file); // save data to sign file = fopen(DataToSignDumpPath, "w"); if (!file) { fprintf(stderr, "Could not open %s for saving data to sign!\n", DataToSignDumpPath); exit(1); } i = fwrite(buffer, dataToSignSize, 1, file); if (i != 1) { fprintf(stderr, "Failed to write data to sign to %s (fwrite() returned %i)!\n", DataToSignDumpPath, i); exit(1); } fclose(file); // save signature offset file = fopen(SigOffsetDumpPath, "w"); if (!file) { fprintf(stderr, "Could not open %s for saving signature offset!\n", SigOffsetDumpPath); exit(1); } i = fprintf(file, "%lli\n", signatureOffset); if (i < 0) { fprintf(stderr, "Failed to write signature offset to %s (fprintf() returned %i)!\n", SigOffsetDumpPath, i); exit(1); } fclose(file); free(buffer); }