11638Srgrimes/* ldbuildid.c - Build Id support routines 21638Srgrimes Copyright (C) 2013-2017 Free Software Foundation, Inc. 31638Srgrimes 41638Srgrimes This file is part of the GNU Binutils. 51638Srgrimes 61638Srgrimes This program is free software; you can redistribute it and/or modify 71638Srgrimes it under the terms of the GNU General Public License as published by 81638Srgrimes the Free Software Foundation; either version 3 of the License, or 91638Srgrimes (at your option) any later version. 101638Srgrimes 111638Srgrimes This program is distributed in the hope that it will be useful, 121638Srgrimes but WITHOUT ANY WARRANTY; without even the implied warranty of 131638Srgrimes MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 141638Srgrimes GNU General Public License for more details. 151638Srgrimes 161638Srgrimes You should have received a copy of the GNU General Public License 171638Srgrimes along with this program; if not, write to the Free Software 181638Srgrimes Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, 191638Srgrimes MA 02110-1301, USA. */ 201638Srgrimes 211638Srgrimes#include "sysdep.h" 221638Srgrimes#include "bfd.h" 231638Srgrimes#include "safe-ctype.h" 241638Srgrimes#include "md5.h" 251638Srgrimes#include "sha1.h" 261638Srgrimes#include "ldbuildid.h" 271638Srgrimes#ifdef __MINGW32__ 281638Srgrimes#include <windows.h> 291638Srgrimes#include <rpcdce.h> 301638Srgrimes#endif 311638Srgrimes 321638Srgrimes#define streq(a,b) strcmp ((a), (b)) == 0 3350476Speter#define strneq(a,b,n) strncmp ((a), (b), (n)) == 0 341638Srgrimes 35279747Straszbfd_boolean 361638Srgrimesvalidate_build_id_style (const char *style) 371638Srgrimes{ 381638Srgrimes if ((streq (style, "md5")) || (streq (style, "sha1")) 391638Srgrimes || (streq (style, "uuid")) || (strneq (style, "0x", 2))) 40107788Sru return TRUE; 411638Srgrimes 42107788Sru return FALSE; 43130582Sru} 4471895Sru 45107788Srubfd_size_type 4671895Srucompute_build_id_size (const char *style) 471638Srgrimes{ 4871895Sru if (streq (style, "md5") || streq (style, "uuid")) 4954338Sdcs return 128 / 8; 5054338Sdcs 51130582Sru if (streq (style, "sha1")) 5271895Sru return 160 / 8; 5354338Sdcs 5454338Sdcs if (strneq (style, "0x", 2)) 55273660Sian { 56273660Sian bfd_size_type size = 0; 57273660Sian /* ID is in string form (hex). Count the bytes. */ 58273660Sian const char *id = style + 2; 59273660Sian 60273660Sian do 61273660Sian { 62273660Sian if (ISXDIGIT (id[0]) && ISXDIGIT (id[1])) 6371895Sru { 6465526Sobrien ++size; 65273660Sian id += 2; 6671895Sru } 6793959Smurray else if (*id == '-' || *id == ':') 6879727Sschweikh ++id; 6979727Sschweikh else 70273660Sian { 71273660Sian size = 0; 72273660Sian break; 73273660Sian } 7454338Sdcs } while (*id != '\0'); 7578824Snik return size; 7678824Snik } 7778824Snik 7878824Snik return 0; 7978824Snik} 8078824Snik 8178824Snikstatic unsigned char 8279797Snikread_hex (const char xdigit) 8371895Sru{ 84138977Sjkoshy if (ISDIGIT (xdigit)) 85138977Sjkoshy return xdigit - '0'; 861638Srgrimes 87138977Sjkoshy if (ISUPPER (xdigit)) 8879727Sschweikh return xdigit - 'A' + 0xa; 891638Srgrimes 901638Srgrimes if (ISLOWER (xdigit)) 911638Srgrimes return xdigit - 'a' + 0xa; 92138977Sjkoshy 93138977Sjkoshy abort (); 941638Srgrimes return 0; 9571895Sru} 9679727Sschweikh 971638Srgrimesbfd_boolean 98157693Sbrueffergenerate_build_id (bfd *abfd, 9971895Sru const char *style, 10047597Snik checksum_fn checksum_contents, 10147597Snik unsigned char *id_bits, 10247597Snik int size ATTRIBUTE_UNUSED) 103157693Sbrueffer{ 104157693Sbrueffer if (streq (style, "md5")) 10571895Sru { 10623524Swosch struct md5_ctx ctx; 10723524Swosch 10823524Swosch md5_init_ctx (&ctx); 10971895Sru if (!(*checksum_contents) (abfd, (sum_fn) &md5_process_bytes, &ctx)) 11078824Snik return FALSE; 11179727Sschweikh md5_finish_ctx (&ctx, id_bits); 1121638Srgrimes } 1131638Srgrimes else if (streq (style, "sha1")) 11415135Smpp { 11593959Smurray struct sha1_ctx ctx; 11693959Smurray 117162286Sjoel sha1_init_ctx (&ctx); 11871895Sru if (!(*checksum_contents) (abfd, (sum_fn) &sha1_process_bytes, &ctx)) 11947597Snik return FALSE; 12047597Snik sha1_finish_ctx (&ctx, id_bits); 12147597Snik } 12247597Snik else if (streq (style, "uuid")) 123157693Sbrueffer { 124157693Sbrueffer#ifndef __MINGW32__ 125157693Sbrueffer int n; 126157693Sbrueffer int fd = open ("/dev/urandom", O_RDONLY); 127157693Sbrueffer 128157693Sbrueffer if (fd < 0) 129157693Sbrueffer return FALSE; 130157693Sbrueffer n = read (fd, id_bits, size); 13171895Sru close (fd); 13223524Swosch if (n < size) 13379727Sschweikh return FALSE; 13423524Swosch#else /* __MINGW32__ */ 135157693Sbrueffer typedef RPC_STATUS (RPC_ENTRY * UuidCreateFn) (UUID *); 136157693Sbrueffer UUID uuid; 137157693Sbrueffer UuidCreateFn uuid_create = 0; 138157693Sbrueffer HMODULE rpc_library = LoadLibrary ("rpcrt4.dll"); 13971895Sru 14056900Skris if (!rpc_library) 1411638Srgrimes return FALSE; 142122859Sgordon uuid_create = (UuidCreateFn) GetProcAddress (rpc_library, "UuidCreate"); 143122859Sgordon if (!uuid_create) 144122859Sgordon { 145122859Sgordon FreeLibrary (rpc_library); 146122859Sgordon return FALSE; 147129480Spjd } 148130582Sru 149129480Spjd if (uuid_create (&uuid) != RPC_S_OK) 150129491Spjd { 151129480Spjd FreeLibrary (rpc_library); 152129480Spjd return FALSE; 153129480Spjd } 154122859Sgordon FreeLibrary (rpc_library); 155130845Smpp memcpy (id_bits, &uuid, 156122859Sgordon (size_t) size < sizeof (UUID) ? (size_t) size : sizeof (UUID)); 157122859Sgordon#endif /* __MINGW32__ */ 158122859Sgordon } 159158409Smarcus else if (strneq (style, "0x", 2)) 160158409Smarcus { 161158409Smarcus /* ID is in string form (hex). Convert to bits. */ 162158409Smarcus const char *id = style + 2; 16371895Sru size_t n = 0; 1641638Srgrimes 1651638Srgrimes do 166279747Strasz { 167279747Strasz if (ISXDIGIT (id[0]) && ISXDIGIT (id[1])) 168279747Strasz { 169279747Strasz id_bits[n] = read_hex (*id++) << 4; 17071895Sru id_bits[n++] |= read_hex (*id++); 171107788Sru } 17223524Swosch else if (*id == '-' || *id == ':') 173164482Srodrigc ++id; 174118647Ssimon else 175118647Ssimon abort (); /* Should have been validated earlier. */ 176118647Ssimon } 177118647Ssimon while (*id != '\0'); 17871895Sru } 17923524Swosch else 18071895Sru abort (); /* Should have been validated earlier. */ 1811638Srgrimes 1821638Srgrimes return TRUE; 18379727Sschweikh} 18485030Smurray