tstdvd.c
上传用户:lsh121205
上传日期:2007-01-08
资源大小:25k
文件大小:8k
源码类别:

DVD

开发平台:

C/C++

  1. /*
  2.  * tstdvd.c
  3.  *
  4.  * Example program showing usage of DVD CSS ioctls
  5.  *
  6.  * Copyright (C) 1999 Andrew T. Veliath <andrewtv@usa.net>
  7.  * See http://www.rpi.edu/~veliaa/linux-dvd for more info.
  8.  */
  9. /* Hacked about by Derek Fawcus <derek@spider.com> such that
  10.  * it can be used as a simple program to authenticate the
  11.  * computer with the DVD-ROM drive.
  12.  *
  13.  * If supplied with one parameter it gets the disk key and
  14.  * saves it to a file.  If supplied with a second parameter
  15.  * (a LBA) then it gets the title key for the supplied LBA.
  16.  *
  17.  * When getting the disk key,  only the first 10 bytes of it
  18.  * are printed.  The whole key is written to the file.
  19.  */
  20. #include <stdio.h>
  21. #include <stdlib.h>
  22. #include <string.h>
  23. #include <time.h>
  24. #include <unistd.h>
  25. #include <fcntl.h>
  26. #include <sys/ioctl.h>
  27. #include <sys/types.h>
  28. #include <sys/stat.h>
  29. #include <sys/types.h>
  30. #include <errno.h>
  31. #if defined(__OpenBSD__)
  32. # include <sys/dvdio.h>
  33. #elif defined(__linux__)
  34. # include <linux/cdrom.h>
  35. #else
  36. # error "Need the DVD ioctls"
  37. #endif
  38. #include "css-auth.h"
  39. byte Challenge[10];
  40. struct block Key1;
  41. struct block Key2;
  42. struct block KeyCheck;
  43. byte DiscKey[10];
  44. int varient = -1;
  45. void print_challenge(const byte *chal)
  46. {
  47. int i;
  48. for (i = 0; i < 10; ++i)
  49. printf(" %02X", chal[9-i] & 0xff);
  50. }
  51. void print_key(const byte *key)
  52. {
  53. int i;
  54. for (i = 0; i < 5; ++i)
  55. printf(" %02X", key[4-i] & 0xff);
  56. }
  57. void print_five(const byte *key)
  58. {
  59. int i;
  60. for (i = 0; i < 5; ++i)
  61. printf(" %02X", key[i] & 0xff);
  62. }
  63. int authenticate_drive(const byte *key)
  64. {
  65. int i;
  66. for (i=0; i<5; i++)
  67. Key1.b[i] = key[4-i];
  68. for (i = 0; i < 32; ++i)
  69. {
  70. CryptKey1(i, Challenge, &KeyCheck);
  71. if (memcmp(KeyCheck.b, Key1.b, 5)==0)
  72. {
  73. varient = i;
  74. printf("Drive Authentic - using varient %dn", i);
  75. return 1;
  76. }
  77. }
  78. if (varient == -1)
  79. printf("Drive would not Authenticaten");
  80. return 0;
  81. }
  82. int GetDiscKey(int fd, int agid, char *key)
  83. {
  84. dvd_struct s;
  85. int index, fdd;
  86. s.type = DVD_STRUCT_DISCKEY;
  87. s.disckey.agid = agid;
  88. memset(s.disckey.value, 0, 2048);
  89. if (ioctl(fd, DVD_READ_STRUCT, &s)<0)
  90. {
  91. printf("Could not read Disc Keyn");
  92. return 0;
  93. }
  94. printf ("Received Disc Key:t");
  95. for (index=0; index<sizeof s.disckey.value; index++)
  96. s.disckey.value[index] ^= key[4 - (index%5)];
  97. for (index=0; index<10; index++) {
  98. printf("%02X ", s.disckey.value[index]);
  99. }
  100. printf ("n");
  101. fdd = open("disk-key", O_WRONLY|O_TRUNC|O_CREAT, 0644);
  102. if (fdd < 0)
  103. printf("Can't create "disk-key"n");
  104. else {
  105. if (write(fdd, s.disckey.value, 2048) != 2048)
  106. printf("Can't write "disk-key"n");
  107. close(fdd);
  108. }
  109. return 1;
  110. }
  111. int GetTitleKey(int fd, int agid, int lba, char *key)
  112. {
  113. dvd_authinfo ai;
  114. int i, fdd;
  115. ai.type = DVD_LU_SEND_TITLE_KEY;
  116. ai.lstk.agid = agid;
  117. ai.lstk.lba = lba;
  118. if (ioctl(fd, DVD_AUTH, &ai)) {
  119. printf("GetTitleKey failedn");
  120. return 0;
  121. }
  122. printf ("Received Title Key:t");
  123. for (i = 0; i < 5; ++i) {
  124. ai.lstk.title_key[i] ^= key[4 - (i%5)];
  125. printf("%02X ", ai.lstk.title_key[i]);
  126. }
  127. putchar('n');
  128. printf(" CPM=%d, CP_SEC=%d, CGMS=%dn", ai.lstk.cpm, ai.lstk.cp_sec, ai.lstk.cgms);
  129. fdd = open("title-key", O_WRONLY|O_TRUNC|O_CREAT, 0644);
  130. if (fdd < 0)
  131. printf("Can't create "title-key"n");
  132. else {
  133. if (write(fdd, ai.lstk.title_key, 5) != 5)
  134. printf("Can't write "title-key"n");
  135. close(fdd);
  136. }
  137. return 1;
  138. }
  139. int GetASF(int fd)
  140. {
  141. dvd_authinfo ai;
  142. ai.type = DVD_LU_SEND_ASF;
  143. ai.lsasf.agid = 0;
  144. ai.lsasf.asf = 0;
  145. if (ioctl(fd, DVD_AUTH, &ai)) {
  146. printf("GetASF failedn");
  147. return 0;
  148. }
  149. printf("%sAuthenticatedn", (ai.lsasf.asf) ? "" : "not ");
  150. return 1;
  151. }
  152. /* Simulation of a non-CSS compliant host (i.e. the authentication fails,
  153.  * but idea is here for a real CSS compliant authentication scheme). */
  154. int
  155. hostauth (dvd_authinfo *ai)
  156. {
  157. int i;
  158. switch (ai->type) {
  159. /* Host data receive (host changes state) */
  160. case DVD_LU_SEND_AGID:
  161. printf("AGID %dn", ai->lsa.agid);
  162. ai->type = DVD_HOST_SEND_CHALLENGE;
  163. break;
  164. case DVD_LU_SEND_KEY1:
  165. printf("LU sent key1: "); print_key(ai->lsk.key); printf("n");
  166. if (!authenticate_drive(ai->lsk.key)) {
  167. ai->type = DVD_AUTH_FAILURE;
  168. return -EINVAL;
  169. }
  170. ai->type = DVD_LU_SEND_CHALLENGE;
  171. break;
  172. case DVD_LU_SEND_CHALLENGE:
  173. for (i = 0; i < 10; ++i)
  174. Challenge[i] = ai->hsc.chal[9-i];
  175. printf("LU sent challenge: "); print_challenge(Challenge); printf("n");
  176. CryptKey2(varient, Challenge, &Key2);
  177. ai->type = DVD_HOST_SEND_KEY2;
  178. break;
  179. /* Host data send */
  180. case DVD_HOST_SEND_CHALLENGE:
  181. for (i = 0; i < 10; ++i)
  182. ai->hsc.chal[9-i] = Challenge[i];
  183. printf("Host sending challenge: "); print_challenge(Challenge); printf("n");
  184. /* Returning data, let LU change state */
  185. break;
  186. case DVD_HOST_SEND_KEY2:
  187. for (i = 0; i < 5; ++i)
  188. ai->hsk.key[4-i] = Key2.b[i];
  189. printf("Host sending key 2: "); print_key(Key2.b); printf("n");
  190. /* Returning data, let LU change state */
  191. break;
  192. default:
  193. printf("Got invalid state %dn", ai->type);
  194. return -EINVAL;
  195. }
  196. return 0;
  197. }
  198. int authenticate(int fd, int title, int lba)
  199. {
  200. dvd_authinfo ai;
  201. dvd_struct dvds;
  202. int i, rv, tries, agid;
  203. memset(&ai, 0, sizeof (ai));
  204. memset(&dvds, 0, sizeof (dvds));
  205. GetASF(fd);
  206. /* Init sequence, request AGID */
  207. for (tries = 1, rv = -1; rv == -1 && tries < 4; ++tries) {
  208. printf("Request AGID [%d]...t", tries);
  209. ai.type = DVD_LU_SEND_AGID;
  210. ai.lsa.agid = 0;
  211. rv = ioctl(fd, DVD_AUTH, &ai);
  212. if (rv == -1) {
  213. perror("N/A, invalidating");
  214. ai.type = DVD_INVALIDATE_AGID;
  215. ai.lsa.agid = 0;
  216. ioctl(fd, DVD_AUTH, &ai);
  217. }
  218. }
  219. if (tries == 4) {
  220. printf("Cannot get AGIDn");
  221. return -1;
  222. }
  223. for (i = 0; i < 10; ++i)
  224. Challenge[i] = i;
  225. /* Send AGID to host */
  226. if (hostauth(&ai) < 0) {
  227. printf("Send AGID to host failedn");
  228. return -1;
  229. }
  230. /* Get challenge from host */
  231. if (hostauth(&ai) < 0) {
  232. printf("Get challenge from host failedn");
  233. return -1;
  234. }
  235. agid = ai.lsa.agid;
  236. /* Send challenge to LU */
  237. if (ioctl(fd, DVD_AUTH, &ai) < 0) {
  238. printf("Send challenge to LU failedn");
  239. return -1;
  240. }
  241. /* Get key1 from LU */
  242. if (ioctl(fd, DVD_AUTH, &ai) < 0) {
  243. printf("Get key1 from LU failedn");
  244. return -1;
  245. }
  246. /* Send key1 to host */
  247. if (hostauth(&ai) < 0) {
  248. printf("Send key1 to host failedn");
  249. return -1;
  250. }
  251. /* Get challenge from LU */
  252. if (ioctl(fd, DVD_AUTH, &ai) < 0) {
  253. printf("Get challenge from LU failedn");
  254. return -1;
  255. }
  256. /* Send challenge to host */
  257. if (hostauth(&ai) < 0) {
  258. printf("Send challenge to host failedn");
  259. return -1;
  260. }
  261. /* Get key2 from host */
  262. if (hostauth(&ai) < 0) {
  263. printf("Get key2 from host failedn");
  264. return -1;
  265. }
  266. /* Send key2 to LU */
  267. if (ioctl(fd, DVD_AUTH, &ai) < 0) {
  268. printf("Send key2 to LU failed (expected)n");
  269. return -1;
  270. }
  271. if (ai.type == DVD_AUTH_ESTABLISHED)
  272. printf("DVD is authenticatedn");
  273. else if (ai.type == DVD_AUTH_FAILURE)
  274. printf("DVD authentication failedn");
  275. memcpy(Challenge, Key1.b, 5);
  276. memcpy(Challenge+5, Key2.b, 5);
  277. CryptBusKey(varient, Challenge, &KeyCheck);
  278. printf("Received Session Key:t");
  279. for (i= 0; i< 5; i++)
  280. {
  281. printf("%02X ", KeyCheck.b[i]);
  282. }
  283. printf("n");
  284. GetASF(fd);
  285. if (title)
  286. GetTitleKey(fd, agid, lba, KeyCheck.b);
  287. else
  288. GetDiscKey(fd, agid, KeyCheck.b);
  289. GetASF(fd);
  290. return 0;
  291. }
  292. #ifndef FIBMAP
  293. #define FIBMAP 1
  294. #endif
  295. int path_to_lba(char *p)
  296. {
  297. int fd, lba = 0;
  298. if ((fd = open(p, O_RDONLY)) == -1) {
  299. perror("DVD vob file:");
  300. return 0;
  301. }
  302. if (ioctl(fd, FIBMAP, &lba) != 0) {
  303. perror("ioctl FIBMAP failed:");
  304. close(fd);
  305. return 0;
  306. }
  307. close(fd);
  308. return lba;
  309. }
  310. int main(int ac, char **av)
  311. {
  312. char *device;
  313. int fd, title = 0, lba = 0;
  314. if (ac < 2) {
  315. fprintf(stderr, "usage: tstdvd <device> [title_path]n");
  316. exit (1);
  317. }
  318. device = av[1];
  319. fd = open(device, O_RDONLY | O_NONBLOCK);
  320. if (fd < 0) {
  321. perror(device);
  322. exit(1);
  323. }
  324. if (ac == 3) {
  325. lba = path_to_lba(av[2]);
  326. title = 1;
  327. }
  328. authenticate(fd, title, lba);
  329. close(fd);
  330. return 0;
  331. }